forked from algorhythms/Algo-Quicksheet
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathchapterLinkedList.tex
More file actions
134 lines (115 loc) · 3.17 KB
/
Copy pathchapterLinkedList.tex
File metadata and controls
134 lines (115 loc) · 3.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
\chapter{Linked List}
\section{Operations}
\subsection{Fundamentals}
Get the $pre$ reference:
\begin{python}
dummy = Node(0)
dummy.next = head
pre = dummy
cur = pre.next
\end{python}
\subsection{Basic Operations}
\begin{enumerate}
\item Get the length
\item Get the $i$-th object
\item Delete a node
\item Reverse
\begin{figure}[]
\centering
\subfloat{\includegraphics[scale=1.0]{ll_reverse}}
\caption{Reverse the linked list}
\label{fig:LABEL}
\end{figure}
\begin{python}
def reverseList(self, head):
dummy = ListNode(0)
dummy.next = head
pre = dummy
cur = pre.next
while pre and cur:
pre, cur.next, cur = cur, pre, cur.next
# incorrect evaluation order:
# pre, cur, cur.next = cur, cur.next, pre
dummy.next.next = None # original head
return pre # new head
\end{python}
Notice: the evaluation order for the swapping the nodes and links.
\end{enumerate}
\subsection{Combined Operations}
In $O(n)$ without extra space:
\begin{enumerate}
\item Determine whether two lists intersects
\item Determine whether the list is palindrome
\item Determine whether the list is acyclic
\end{enumerate}
\section{Combinations}
\subsection{LRU}
Core clues:
\begin{enumerate}
\item Ensure $O(1)$ find $O(1)$ deletion.
\item Doubly linked list + map.
\item Keep both \pyinline{head} and \pyinline{tail} pointer.
\item Operations on doubly linked list are case by case.
\end{enumerate}
\begin{python}
class Node(object):
def __init__(self, key, val):
self.key = key
self.val = val
self.pre, self.next = None, None
class LRUCache(object):
def __init__(self, capacity):
self.cap = capacity
self.map = {} # key to node
self.head = None
self.tail = None
def get(self, key):
if key in self.map:
cur = self.map[key]
self._elevate(cur)
return cur.val
return -1
def set(self, key, value):
if key in self.map:
cur = self.map[key]
cur.val = value
self._elevate(cur)
else:
cur = Node(key, value)
self.map[key] = cur
self._appendleft(cur)
if len(self.map) > self.cap:
last = self._pop()
del self.map[last.key]
# doubly linked-list operations only
def _appendleft(self, cur):
"""Normal or initially empty"""
if not self.head and not self.tail:
self.head = cur
self.tail = cur
return
head = self.head
cur.next, cur.pre, head.pre = head, None, cur
self.head = cur
def _pop(self):
"""Normal or resulting empty"""
last = self.tail
if self.head == self.tail:
self.head, self.tail = None, None
return last
pre = last.pre
pre.next = None
self.tail = pre
return last
def _elevate(self, cur):
"""Head, Tail, Middle"""
pre, nxt = cur.pre, cur.next
if not pre:
return
elif not nxt:
assert self.tail == cur
self._pop()
else:
pre.next, nxt.pre = nxt, pre
self._appendleft(cur)
\end{python}