Lintcode
Loop from end to beginning
Merge Sorted Array
Just loop with 2 index If one array is large, use binary search
Merge Two Sorted Arrays
Classic merge two list If one list is very large, then can use binarySearch
Merge Two Sorted Lists
1. Using heap to store every head Using dummy node to construct the new list 2. D&C, divide into two lists pair, and using merge two list to do it 3. Merge list 2by2, similar to D&C but can do in iterate solution
Merge k Sorted Lists
slow, fast pointers
Middle of Linked List
Binary Search 很随便,找第一个,最后一个,哪个都行
Classical Binary Search
• state: f[i]表示跳到第i个位置的方案总数 • function: f[i] = f[i-1] + f[i-2] • initialize: f[0] = 1 • answer: f[n] // index from 0~n
Climbing Stairs
Using new list to store result Use carry, don't forget to check carry in the end
Add Two Numbers
First reverse Then add Then reverse again
Add Two Numbers II
DP 2-D array int n = A.length; int[][] maxVal = new int[n + 1][m + 1]; maxVal[0][0] = 0; for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { if (j - A[i - 1] >= 0) { maxVal[i][j] = Math.max(maxVal[i - 1][j], maxVal[i - 1][j - A[i - 1]] + V[i - 1]); } else { maxVal[i][j] = maxVal[i - 1][j]; } } } return maxVal[n][m];
Backpack II
D&C Result type contain height and isBalanced
Balanced Binary Tree
Similar to maximum subarray int min = Integer.MAX_VALUE; int max_profit = 0; for (int i = 0; i < prices.length; i++) { min = Math.min(min, prices[i]); max_profit = Math.max(max_profit, prices[i] - min); } Or you can just use greedy
Best Time to Buy and Sell Stock
Greedy, int diff = prices[i+1] - prices[i]; if (diff > 0) { profit += diff; }
Best Time to Buy and Sell Stock II
Using stack first push all left node to it has a cur point to the cur node (not in stack) when hashNext() just check if cur == null next() result is cur, if cur.right != null add all left nodes in cur.right if cur.right == null, just pop from stack
Binary Search Tree Iterator
Classical level order traversal
Binary Tree Level Order Traversal
D& C Result 里包含root2any 和 any2any int passRoot = Math.max(0, left.root2any) + Math.max(0, right.root2any) + root.val; int any2any = Math.max(passRoot, Math.max(left.any2any, right.any2any)); int root2any = Math.max(0, Math.max(left.root2any, right.root2any)) + root.val;
Binary Tree Maximum Path Sum
D&C Math.max(0, Math.max(left, right)) + root.val
Binary Tree Maximum Path Sum II
D & C root在left和right的头上加val 特殊处理叶子结点的情况
Binary Tree Path Sum
1. traversal pass the result 2. D&C, using list.addAll to add left list and right list
Binary Tree Preorder Traversal
double loop use one value row to record current enemy between walls in the current row use cols[] to record current enemy between walls in the current column when reach i = 0 or j = 0 or grid[i][j] = 'W', reset row or col[j], and search until the next wall to count enemy and store in row and col[i] When outer double loop grid[i][j] = '0', check if row + col[j] > max
Bomb Enemy
找出所有的房子,然后再找到所有的空地计算它离所有房子的距离 可以用一个sorted的x list和preSum list of x,来优化计算距离,先通过binary search找到当前点在x的位置,然后用preSum得出距离 这题不能用median的做法,因为不能在有房子的地方建post office
Build Post Office
Classical binary search only one time need the result must be between the start and end
Closest Number in Sorted Array
Greedy 当sum <= 0时重新开始 可以用传统preSum做,但是greedy比较方便
Continuous Subarray Sum
同时保留maxPreSum和minPreSum,反区间采用sum - min的方法酸 要注意的是maxPreSum的时候要处理反区间为空的情况 也可以用greedy来做,想法相似
Continuous Subarray Sum II
1. traversal: have a dummy head and pre, inorder traversal, DoublyListNode cur = new DoublyListNode(root.val); bstToDoublyList(root.left); pre.next = cur; cur.prev = pre; pre = cur; bstToDoublyList(root.right); 2. D&C: design a return type including the beginning and ending of the list
Convert Binary Search Tree to Doubly Linked List
Find mid, then divide & conquer
Convert Sorted List to Balanced BST
Use a hashmap store old_node to new node Iterate through old_list, if old_node or old_node.random not in map, add it in map. Then new_list just simply add from map No extra space 比较麻烦,/*第一遍扫的时候巧妙运用next指针, 开始数组是1->2->3->4 。 然后扫描过程中 先建立copy节点 1->1`->2->2`->3->3`->4->4`, 然后第二遍copy的时候去建立边的copy, 拆分节点, 一边扫描一边拆成两个链表,这里用到两个dummy node。第一个链表变回 1->2->3 , 然后第二变成 1`->2`->3` */
Copy List with Random Pointer
while(node.next != null) { node.val = node.next.val; if(node.next.next == null) { node.next = null; } else { node = node.next; } }
Delete Node in the Middle of Singly Linked List
state: f[i][j] 表示 S的前i个字符中选取T的前j个字符,有多少种方案 • function: f[i][j] = f[i - 1][j] + f[i - 1][j - 1] // S[i-1] == T[j-1] • = f[i - 1][j] // S[i-1] != T[j-1] • initialize: f[i][0] = 1, f[0][j] = 0 (j > 0) • answer: f[n][m] (n = sizeof(S), m = sizeof(T))
Distinct Subsequences
假设最小的次数是X 第i次往上爬X-i+1格 然后问题就变成1+2+......+X大于等于n的最小的X是多少 贪心算法, 每次爬多少都是找的局部最优, 越往上爬剩下的子问题规模越小, 所以全局最优 因为第一个瓶子每爬一下, 第二个瓶子拥有的检查次数都要减少1 因为drop的次数被第一个瓶子多用掉了一次, 所以步长不能超多X-i+1, 如果比X-i+1小 就不是最优
Drop Eggs
state: f[i][j]表示A的前i个字符最少要用几次编辑可以变成B的前j个字符 • function: f[i][j] = MIN(f[i-1][j]+1, f[i][j-1]+1, f[i-1][j-1]) // A[i - 1] == B[j - 1] • = MIN(f[i-1][j]+1, f[i][j-1]+1, f[i-1][j-1]+1) // A[i - 1] != B[j - 1] • initialize: f[i][0] = i, f[0][j] = j • answer: f[n][m]
Edit Distance
Union-Find+HashMap,union的时候要遍历其中一个set乘上对应的factor 或者用graph dfs来做,一个a/b = v相当于a到b的一条边重v,和b到a的一条边重1/v
Evaluate Divisione
Binary Search Remember the graph! Choose the last number as target the condition is the first number less then the target
Find Minimum in Rotated Sorted Array
最坏的必然是O(n), [1,1,1,1,0,1,1,1] 写binarysearch 要和当时的end来比
Find Minimum in Rotated Sorted Array II
Binary Search the condition is A[mid + 1], A[mid] and A[mid - 1]
Find Peak Element
Binary Search find the first item satisfy the condition
First Bad Version
Binary Search Standard search for the first position search
First Position of Target
DP Backpack State: f[i][j] 前i个第i个调整为j时的最小cost Fun: f[i][v] = min(f[i-1][v'] + |A[i]-v|, |v-v'| <= target) Init: f[0][j] = 0, f[i][j] = Integer.MAX_VALUE (i > 0) Res: min(f[n][j]) for (int i = 1; i <= n; i++) { for (int j = 0; j <= 100; j++) { cost[i][j] = Integer.MAX_VALUE; } } for (int i = 1; i <= n; i++) { for (int j = 0; j <= 100; j++) { if (cost[i - 1][j] != Integer.MAX_VALUE) { for (int k = Math.max(0, j - target); k <= Math.min(100, j + target); k++) { cost[i][k] = Math.min(cost[i][k], cost[i - 1][j] + Math.abs(k - A.get(i - 1))); } } } } int res = Integer.MAX_VALUE; for (int i = 0; i <= 100; i++) { res = Math.min(res, cost[n][i]); }
Minimum Adjustment Cost
Until leaf! if(root.left == null && root.right == null) { return 1; } int left = root.left == null?Integer.MAX_VALUE: minDepth(root.left); int right = root.right == null?Integer.MAX_VALUE: minDepth(root.right); return Math.min(left, right) + 1;
Minimum Depth of Binary Tree
• state: f[x][y]从起点走到x,y的min • function: f[x][y] = min(f[x-1][y], f[x][y-1]) + A[x][y] • intialize: f[i][0] = sum(0 - i) f[0][i] = sum(0 - j) • answer: f[n-1][m-1]
Minimum Path Sum
2 pointer 就可以,当快的为null就停下
Nth to Last Node in List
DP 2-D array Backpack IV In each iteration, sum the [i-1][j - k*num[i - 1]] the target should start from 0
Number of Ways to represent N cents
• state: f[i]表示"前i"个字符能否被完美切分 • function: f[i] = OR{f[j]} 其中 j < i && j+1~i is a word • OR 运算的意思 • 假如 j = 0, 1, 3, 5 时满足 j < i && j+1~i is a word • 那么 f[i] = f[0] || f[1] || f[3] || f[5] • initialize: f[0] = true • answer: f[n] • 注意:切分位置的枚举->单词长度枚举 O(NL2) • N: 字符串长度 • L: 最长的单词的长度
Word Break
将n个数看做n个木桩,目的是从某个木桩出发,从前向后,从低往高,看做多能踩多少个木桩。 • state: f[i] 表示(从任意某个木桩)跳到第i个木桩,最多踩过多少根木桩 • function: f[i] = max{f[j] + 1}, j必须满足 j < i && nums[j] <= nums[i] • initialize: f[0..n-1] = 1 • answer: max{f[0..n-1]}
Longest Increasing Subsequence
Don't need to define own Result type if find the node just return node if find both return root
Lowest Common Ancestor
D&C return max(left, right) + 1
Maximum Depth of Binary Tree
Binary Search Compare with neighbor num since mid will never = 0/n, no need to check mid - 1 >= 0 or mid + 1 < n
Maximum Number in Mountain Sequence
Greedy 当sum <= 0时重新开始 可以用传统preSum做,但是greedy比较方便
Maximum Subarray
D & C left, left && right, right
Identical Binary Tree
If the root <= target, successor = root, root = root.left If root > target, root = root.right, successor unchanged
Inorder Successor in Binary Search Tree
Have a new list for insertion sort, then insert node in head one by one
Insertion Sort List
state: f[i][j]表示s1的前i个字符和s2的前j个字符能否交替组成s3的前i+j个字符 function: f[i][j] = (f[i-1][j] && (s1[i-1]==s3[i+j-1]) || (f[i][j-1] && (s2[j-1]==s3[i+j-1]) initialize: f[i][0] = (s1[0..i-1] == s3[0..i-1]) f[0][j] = (s2[0..j-1] == s3[0..j-1]) answer: f[n][m], n = sizeof(s1), m = sizeof(s2)
Interleaving String
1. HashSet 2. Sort and two pointers merge 3. Sort and binary search
Intersection of Two Arrays
最优算法:贪心法,时间复杂度 O(n) 用一个变量保存你最多可以跳多远 • 次优算法:动态规划,时间复杂度 O(n^2) • state: f[i]代表我能否跳到第i个位置 • function: f[i] = OR{f[j]} 其中 j < i && j能够跳到i • 解释:什么是 OR 运算? • 比如满足 j < i && j 能够跳到 i 的 j 有 0, 1, 4, 7 • 那么 f[i] = f[0] || f[1] || f[4] || f[7] • initialize: f[0] = true; • answer: f[n-1]
Jump Game
最优算法:贪心法 O(n) 类似双指针,start, end 初始化为0,从start到end找最远,然后start = end + 1, end = farthest • 次优算法:动态规划 O(n^2) • state: f[i]代表我跳到第 i个位置最少需要几步 • function: f[i] = MIN{f[j]+1} 其中 j < i && j能够跳到i • initialize: f[0] = 0; • answer: f[n-1]
Jump Game II
First Binary search find first >= position Then two pointers go to left and right
K Closest Numbers In Sorted Array
Binary Search <= start = mid > end = mid end == then start ==
Last Position of Target
Slow and fast pointer, if slow can equal to fast then true
Linked List Cycle
Slow fast pointer, after first meet, set slow to head, fast = fast.next, then use the same speed until they meet
Linked List Cycle II
state: f[i][j]表示前i个字符配上前j个字符的LCS的长度 • function: f[i][j] = MAX(f[i-1][j], f[i][j-1], f[i-1][j-1] + 1) // A[i - 1] == B[j - 1] • else f[i][j] = MAX(f[i-1][j], f[i][j-1]) • intialize: f[i][0] = 0 f[0][j] = 0 • answer: f[n][m]
Longest Common Subsequence
state: f[i][j]表示前i个字符配上前j个字符的LCS的长度 • function: f[i][j] = f[i - 1][j - 1] + 1// A[i - 1] == B[j - 1] • else f[i][j] = 0 • intialize: f[i][0] = 0 f[0][j] = 0 • answer: f[n][m]
Longest Common Substring
Use the findkth function Get the start + k/2 value for both array, if val1 < val2 then search start1 + k/2, start2 for k/2, or vice versa O(log (m + n))
Median of two Sorted Arrays
Reverse right half then compare
Palindrome Linked List
• state: f[i]表示前i个字符组成的子串能被分割为最少多少个回文串 • function: f[i] = MIN{f[j]+1}, j < i && j+1 ~ i这一段是一个回文串 • initialize: f[i] = i (f[0] = 0) • answer: f[n] - 1
Palindrome Partitioning II
Using extra two list to record node less than x, and greater or equal to x, then chain them together
Partition List
No need for dummy 相等删next 不相等往后移
Remove Duplicates from Sorted List
if cur.next.val == cur.next.next.val { int val = cur.next.val while (cur.next.next.val == val) { cur.next = cur.next.next
Remove Duplicates from Sorted List II
Using hashset, check cur.next
Remove Duplicates from Unsorted List
check cur.next
Remove Linked List Elements
Slow fast pointer
Remove Nth Node From End of List
Find mid then reverse from mid to end Then start from both start and end, merge two list
Reorder List
classic pre and cur
Reverse Linked List
Do it on the fly, just need to know the current step Need to figure out really clear the relationship between step and cur, it's when cur move to n node, it is step n.
Reverse Linked List II
first check if k > len, k = k % len then slow and fast pointer, remember we want to find the one before the real one
Rotate List
Binary Search Find the first value greater then target
Search Insert Position
Binary Search 1. Treat as a 1-D array 2. find the last start less then target, then binary search
Search a 2D Matrix
Binary Search 先找符合条件的row和col区间 然后在区间里每行再做binary search
Search a 2D Matrix II
两个binary search找边界
Search for a Range
Binary Search Remember the graph! First compare the mid with the end to decide which side the mid is in Then for each side, compare the target with (start, mid) or (end, mid), to decide which side of mid the target is in
Search in Rotated Sorted Array
// 这个问题在面试中不会让实现完整程序 // 只需要举出能够最坏情况的数据是 [1,1,1,1... 1] 里有一个0即可。 // 在这种情况下是无法使用二分法的,复杂度是O(n) // 因此写个for循环最坏也是O(n),那就写个for循环就好了 // 如果你觉得,不是每个情况都是最坏情况,你想用二分法解决不是最坏情况的情况,那你就写一个二分吧。 // 反正面试考的不是你在这个题上会不会用二分法。这个题的考点是你想不想得到最坏情况。
Search in Rotated Sorted Array II
First using pow(2, x) Then binary search
Search in a Big Sorted Array
Merge sort is straightforward, find mid first, then merge sort left and right, then merge Quick sort use 3 tmp list: less then, equal, and greater then, recursively sort less then and greater then, then concat 3 together
Sort List
对preSum排序 减去相邻的preSum得到最小的diff 自定义一个preSum的类比较方便
Subarray Sum Closest
preSum 排序,然后遍历preSum 用binarySearch找到与当前preSum差值符合条件的区域 Note: 两边都需要包括等于的情况!所以某一边需要+1/-1
Subarray Sum II
Dummy head swap cur and pre cur != null && cur.next != null
Swap Nodes in Pairs
Dummy head need to check if n1 and n2 is neighbor Each node need to keep it's pre and next
Swap Two Nodes in Linked List
D & C left, right && right, left
Symmetric Binary Tree
两个binary search找头和尾
Total Occurrence of Target
• state: sum[i][j]从0,0 到 i, j 的最小sm • function: f[i][j] = min(f[i-1][j], f[i - 1][j-1]) + A[j][j] • intialize: f[i][0] = sum(0 - i, A[i][0]) f[i][i] = sum(0 - j, A[i][i]) • answer: min(sum[m - 1][j])
Triangle
D & C (left, left & right, right) || (left, right && right, left)
Tweaked Identical Binary Tree
• state: f[x][y]从起点走到x,y的最短路径 • function: f[x][y] = min(f[x-1][y], f[x][y-1]) + A[x][y] • intialize: f[i][0] = sum(0,0 ~ i,0) f[0][i] = sum(0,0 ~ 0,i) • answer: f[n-1][m-1]
Unique Paths
Same as Unique path Except when init, every thing after obstacle is 0 And in the double loop, if obstacle then 0
Unique Paths II
D&C Result type contains max, min and isValid
Validate Binary Search Tree
swap the unordered neighbor, you can prove that after swap the correct order still hold for the previous series
Wiggle Sort
quick select to find the mid value then put value greater then mid and smaller than mid value into odd and even positions from both ends (or from one end)
Wiggle Sort II
Binary Search Every time calculate piece num as condition find the last satisfy condition
Wood Cut
用一个boolean表示现在是谁,两个index表示当前位置 注意v1长度为0的情况 也可以用两个iterator来做
Zigzag Iterator
ArrayList of iterators iters Once one iterator doesn't have next, remove check iters.size() > 0 for hasNext()
Zigzag Iterator II
3-D array formal i element choose j can sum to t int n = A.length; int[][][] sum = new int[n + 1][k + 1][target + 1]; for (int i = 0; i <= n; i++) { sum[i][0][0] = 1; } for (int i = 1; i <= n; i++) { for (int j = 1; j <= k; j++) { for (int t = 1; t <= target; t++) { if (t - A[i - 1] >= 0) { sum[i][j][t] = sum[i - 1][j][t] + sum[i - 1][j - 1][t - A[i - 1]]; } else { sum[i][j][t] = sum[i - 1][j][t]; } } } } return sum[n][k][target];
k Sum
Two pointer KMP better
strStr