-
Notifications
You must be signed in to change notification settings - Fork 75
Expand file tree
/
Copy pathchapterBasicDataStructures.tex
More file actions
135 lines (116 loc) · 3.9 KB
/
chapterBasicDataStructures.tex
File metadata and controls
135 lines (116 loc) · 3.9 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
135
% !TEX root = algo-quicksheet.tex
\chapter{Basic Data Structures}
\section{Introduction}
Abstract Data Types (ADT):
\begin{enumerate}
\item Queue
\item Stack
\item HashMap
\end{enumerate}
Implementation (for both queue and stack):
\begin{enumerate}
\item Linked List
\item Resizing Array:
\begin{enumerate}
\item Doubling: when full (100\%).
\item Halfing: when one-quarter full (25\%).
\end{enumerate}
\end{enumerate}
Python Library:
\begin{enumerate}
\item \pythoninline{collections.deque} \footnote{The lowercase and uppercase naming in Python collections are awkward: \href{http://stackoverflow.com/questions/18953681/naming-convention-in-collections-why-are-some-lowercase-and-others-capwords}{discussion}.}
\item \pythoninline{list}
\item \pythoninline{dict, OrderedDict, defaultdict}
\end{enumerate}
Java Library:
\begin{enumerate}
\item \javainline{java.util.Stack<E>}
\item \javainline{java.util.LinkedList<E>}
\item \javainline{java.util.HashMap<K, V>; java.util.TreeMap<K, V>}
\end{enumerate}
\section{Python Library}
\begin{python}
from collections import defaultdict
# defaultdict take constructor func as param
counter = defaultdict(int)
G = defaultdict(list) # graph of v -> neighbors
G = defaultdict(dict) # G[s][e] -> weight
G = defaultdict(lambda: defaultdict(int)) # G[s][e] -> weight
from collections import deque
path = deque()
path.appendleft("a")
path.append("b")
path.popleft()
path.pop()
path = deque(sorted(path))
import heapq
l = [] # list
heapq.heappush(l, "a")
heapq.heappop(l)
heapq.heapify(l)
heapq.heappushpop(l, "b")
heapq.nsmallest(3, l)
\end{python}
\section{Stack}
\subsection{Stack and Recursion}
How a compiler implements a function:
\begin{enumerate}
\item Function call: push local environment and return address
\item Return: pop return address and local environment.
\end{enumerate}
Recursive function: function calls itself. It can always be implemented by using an explicit stack to remove recursion.
Stack can convert recursive DFS to iterative.
\subsection{Usage}
The core philosophy of using stack is to maintain a relationship invariant among stack element.
The \textbf{relationship invariants} can be:
\begin{enumerate}
\item strictly asc/ strictly desc
\item non-desc/ non-asc
\end{enumerate}
\subsection{Unpaired Parentheses}
\runinhead{Longest Valid Parentheses.}
Given a string containing just the characters `(' and `)', find the length of the longest valid (well-formed) parentheses substring. Core clues:
\begin{enumerate}
\item \textbf{Invariant}: Stack holds the INDEX of UNPAIRED brackets, either ( or ). \footnote{The stack should always hold indices, rather than values.}
\item Thus, \pyinline{stk[-1]} stores the last unpaired bracket.
\item The length of the well-formed parentheses is: if currently \textbf{valid}, current scanning index \pyinline{idx} minus the last \textbf{invalid} index of bracket \pyinline{stk[-1]}
\end{enumerate}
\begin{python}
def longestValidParentheses(self, s):
stk = []
maxa = 0
for idx, val in enumerate(s):
if val == ")" and stk and s[stk[-1]] == "(":
stk.pop()
if not stk:
maxa = max(maxa, idx+1)
else:
maxa = max(maxa, idx-stk[-1])
else:
stk.append(idx)
return maxa
\end{python}
\section{Map}
\subsection{Math relations}
\textbf{1-1 Map}. Mathematically, full projection. One map, dual entries.
\begin{python}
class OneToOneMap:
def __init__(self):
self.m = {} # keep a single map
def set(self, a, b):
self.m[a] = b
self.m[b] = a
def get(self, a):
return self.m.get(a)
\end{python}
\subsection{Operations}
\runinhead{Sorting by value.} Sort the map entries by values \pyinline{itemgetter}.
\begin{python}
from operators import itemgetter
sorted(hm.items(), key=itemgetter(1), reverse=True)
sorted(hm.items(), key=lambda x: x[1], reverse=True)
\end{python}
\section{Monotonic Stack}
Ref array \ref{monostack}
\section{Monotonic Queue}
Ref array \ref{monoqueue}