理论基础:熟悉常见的数据结构、起码看过一本算法入门书
git clone https://github.com/shenwl/algorithm-java.git
cd algorithm-java
mvn install
mvn clean test
- Clarification
- Possible solutions
- compare(time/space)
- optimal(加强)
- Coding
- Test cases
- Array
- Stack/Queue
- PriorityQueue(heap)
- LinkedList(single/double)
- Tree/BinaryTree
- BST
- HashTable
- Disjoint Set
- Trie
- BloomFilter
- LRU Cache
- General Coding
- InOrder/PreOrder/PostOrder Traversal
- Greedy
- Recursion/Backtrace
- Breadth-first/Depth-first Search
- Divide and Conquer
- Dynamic Programming
- Binary Search
- Graph
- leetcode
- 206: reverse-linked-list (easy)
- 24: swap-nodes-in-pairs (mid)
- 141: linked-list-cycle (easy)
- 142: linked-list-cycle-ii (mid)
- 25: reverse-nodes-in-k-group (hard)
- leetcode
- 20: valid-parentheses (easy)
- 225: implement-stack-using-queues (easy)
- 232: implement-queue-using-stacks (easy)
- 正常入,按优先级出
- 实现机制
- leetcode
- 703: kth-largest-element-in-a-stream (easy)
- 239: sliding-window-maximum (hard)
-
HashTable & Hash Function & Collisions
-
Map vs Set
-
HashMap, HashSet, TreeMap, TreeSet
-
leetcode
- 242: valid-anagram (easy)
- 1: two-sum (easy)
- 15: 3sum (mid)
- 18: 4sum (mid)
-
Tree, Binary Tree, BST
- 经典问题:分层打印二叉树
-
Graph
- 图论算法
- 最短路径问题
-
leetcode
- 98: validate-binary-search-tree (mid)
- 235: lowest-common-ancestor-of-a-binary-search-tree (easy)
- 236: lowest-common-ancestor-of-a-binary-tree (mid)
-
pre-order: root-left-right
-
in-order: left-root-right
-
post-order: left-right-root
-
代码演示
def preorder(self, root): if root: self.traverse_path.append(root.val) preorder(root.left) preorder(root.right) def inorder(self, root): if root: inorder(root.left) self.traverse_path.append(root.val) inorder(root.right) def postorder(self, root): if root: postorder(root.left) postorder(root.right) self.traverse_path.append(root.val)
-
Recursion
- 是实现很多其他算法的基础
- 递归 - 循环,通过函数体来进行循环
- 递归的问题:斐波那契算法为例,重复的子计算过多
-
Divide & Conquer
- 把大问题剖析为子问题:split/merge
- 和递归一样,当出现重复计算时,分治效率并不高,动态规划或者子问题记忆等方法的更合适
-
leetcode
- 50: powx-n (mid)
- 169: majority-element (easy)
-
什么是贪心算法?
- 在对问题求解时,总是做出在当前看来最好的选择。
-
何种情况下用到贪心算法?
- 问题能够分成子问题解决,子问题的最优解能递推到最终问题的最优解(可遇不可求)
- 贪心和DP的不同在于,它对每个子问题的解决方案都做出选择,不能回退
- 动态规划会保存以前运算的结果,并根据以前的结果对当前进行选择,有回退功能
-
leetcode
- 122: best-time-to-buy-and-sell-stock-ii
-
在树 (图/状态集) 中寻找特定节点
-
BFS:从根节点开始扩散,一层一层找
- 使用队列去存放节点
def bfs(graph, start, end): queue = [] queue.append([start]) # 树可以省略visited记录,但是图不行 visited.add(start) while queue: node = queue.pop() visited.add(node) # 处理逻辑 process(node) # 扫描没访问过的后继节点 nodes = generate_related_nodes(node) queue.push(nodes) # ...
-
一直往下走,到最后一个了再往回,递归写法:
visited = set() def dfs(node, visited): visited.add(node) # process current node # ... for next_node in node.children(): if not next_node in visited: dps(next_node, visited)
-
非递归写法:
def dfs(tree): if tree.root is None: return p[] visited, stack = [], [tree.root] while stack: node = stack.pop() visited.add(node) # 扫描没访问过的后继节点 nodes = generate_related_nodes(node) stack.push(nodes)
-
BFS & DFS leetcode:
- 102: Binary Tree Level Order