├── pic_explanation ├── pascal.jpg ├── linkedlist cycle.jpg └── jumping algorithm.png ├── XOR Swapping Method.md ├── GCD.md ├── String.md ├── Majority Element.md ├── Intersection of Two Arrays.md ├── Find Peak Element.md ├── Pascal Triangle.md ├── Problems with Math Solutions.md ├── Contains Duplicate.md ├── LinkedList with Fast & Slow Pointers.md ├── Dynamic Programming-2D.md ├── Binary Search Coding Principles.md ├── Best Time to Buy and Sell Stock.md ├── Linked List Cycle.md ├── Dynamic Programming-1D.md ├── Heap.md ├── Kth Smallest Element in a BST ├── rotation.md ├── Tree Traversal.md ├── Stack.md ├── README.md ├── Backtracking.md ├── Classic Backtrackings.md └── k-Sum.md /pic_explanation/pascal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tongzhang1994/LeetCode-Summary/HEAD/pic_explanation/pascal.jpg -------------------------------------------------------------------------------- /pic_explanation/linkedlist cycle.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tongzhang1994/LeetCode-Summary/HEAD/pic_explanation/linkedlist cycle.jpg -------------------------------------------------------------------------------- /pic_explanation/jumping algorithm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tongzhang1994/LeetCode-Summary/HEAD/pic_explanation/jumping algorithm.png -------------------------------------------------------------------------------- /XOR Swapping Method.md: -------------------------------------------------------------------------------- 1 | # XOR Swapping Method 2 | 3 | Using XOR can swap two elements without using extra memory. Look at the following code with comments and you will understand how it works. 4 | 5 | ```java 6 | void swap(int a, int b){ 7 | a ^= b; 8 | b ^= a; //b=b^(a^b)=a 9 | a ^= b; //a=(a^b)^(b^a^b)=b 10 | } 11 | ``` 12 | -------------------------------------------------------------------------------- /GCD.md: -------------------------------------------------------------------------------- 1 | # GCD 2 | 3 | There are many algorithms to calculate the Greatest Common Divisor. Here is a famous and easy-to-understand one. 4 | 5 | Please refer to: [Euclidean algorithm](https://en.wikipedia.org/wiki/Euclidean_algorithm) 6 | 7 | A java version. 8 | 9 | ```java 10 | int gcd(int a, int b) { 11 | if (b == 0) return a; 12 | else return gcd(b, a % b); 13 | } 14 | ``` -------------------------------------------------------------------------------- /String.md: -------------------------------------------------------------------------------- 1 | # String 2 | 3 | ## [Restore IP Addresses](https://leetcode.com/problems/restore-ip-addresses/) 4 | 5 | **Solution 1:** 6 | 7 | Idea is simple: Use 3 iteration to go through the input string, split it into 3 substring with length less than 4, check the validity of each substring. If all are valid, then add them into result list. 8 | 9 | ```java 10 | public List restoreIpAddresses(String s) { 11 | List res=new ArrayList<>(); 12 | int len=s.length(); 13 | for(int i=1;i<4&&i3||s.length()==0||s.length()>1&&s.charAt(0)=='0'||Integer.parseInt(s)>255) return false; 24 | return true; 25 | } 26 | ``` 27 | 28 | **Solution 2: backtracking** 29 | 30 | This problem can be solved with backtracking method. Refer to [this post](https://discuss.leetcode.com/topic/4742/very-simple-dfs-solution). 31 | -------------------------------------------------------------------------------- /Majority Element.md: -------------------------------------------------------------------------------- 1 | # Majority Element 2 | 3 | ## [Majority Element](https://leetcode.com/problems/majority-element/) 4 | 5 | There are two ways to find the `majority element (which appears more than ⌊ n/2 ⌋ times)` in an array. One is simply sort the array and return the middle element, which takes O(nlogn) time. The other one is the famous [`Boyer-Moore Majority Vote Algorithm`](http://www.cs.utexas.edu/~moore/best-ideas/mjrty/index.html), which takes linear time. 6 | 7 | ```java 8 | public int majorityElement(int[] nums) { 9 | Arrays.sort(nums);//O(nlogn) 10 | return nums[nums.length/2]; 11 | } 12 | ``` 13 | 14 | Please refer to the link above before you see the following code. 15 | 16 | ```java 17 | public int majorityElement(int[] nums) { 18 | //O(n) Boyer-Moore Majority Vote Algorithm 19 | int count=1,maj=nums[0]; 20 | for(int i=1;i *NOTE: Boyer-Moore Majority Vote Algorithm does not garruntee a majority. But* ***if you must confirm that the chosen element is indeed the majority element, you must take one more linear pass through the data to do it***. -------------------------------------------------------------------------------- /Intersection of Two Arrays.md: -------------------------------------------------------------------------------- 1 | # Intersection of Two Arrays 2 | 3 | ## [Intersection of Two Arrays I](https://leetcode.com/problems/intersection-of-two-arrays/) 4 | 5 | 1.Use two HashSets, Time complexity: O(n) 6 | 7 | ```java 8 | public int[] intersection(int[] nums1, int[] nums2) { 9 | Set set=new HashSet<>(); 10 | Set intersect=new HashSet<>(); 11 | for(int n:nums1) set.add(n); 12 | for(int n:nums2) 13 | if(set.contains(n)) intersect.add(n); 14 | int[] res=new int[intersect.size()]; 15 | int i=0; 16 | for(Integer n:intersect) res[i++]=n; 17 | return res; 18 | } 19 | ``` 20 | 21 | ***NOTICE: The time complexity of HashSet.contains() is [O(1)](http://stackoverflow.com/questions/25247854/hashset-contains-performance).*** 22 | 23 | 24 | 2.We can also use the new features in Java 8. 25 | 26 | ```java 27 | public int[] intersection(int[] nums1, int[] nums2) { 28 | Set set = Arrays.stream(nums2).boxed().collect(Collectors.toSet()); 29 | return Arrays.stream(nums1).distinct().filter(e-> set.contains(e)).toArray(); 30 | } 31 | ``` 32 | 33 | 34 | Reference: [Java8初体验](http://ifeve.com/stream/) 35 |
36 | 37 | P.S. There are more solutions to this problem. You can find them at [https://discuss.leetcode.com/topic/45685/three-java-solutions](https://discuss.leetcode.com/topic/45685/three-java-solutions) -------------------------------------------------------------------------------- /Find Peak Element.md: -------------------------------------------------------------------------------- 1 | # [Find Peak Element](https://leetcode.com/problems/find-peak-element/) 2 | 3 | The problem discription says that 'Your solution should be in logarithmic complexity'. This explicitly indicates a Binary Search Algorithm, which has `O(logn)` complexity. 4 | 5 | NOTE: `A peak element is an element that is greater than its neighbors.` If the last element we found has only one neighber, namely the first or last element of the initial array, then it is the peak. (the array is in increasing/decreasing order) 6 | 7 | ```java 8 | public int findPeakElement(int[] nums) { 9 | int low=0,high=nums.length-1; 10 | while(lownums[mid+1]) high=mid; 13 | else low=mid+1; 14 | } 15 | return low; 16 | } 17 | ``` 18 | 19 | Then you may ask that why is using binary searching on unsorted array reasonable in this problem. That is because the problem said that `The array may contain multiple peaks, in that case return the index to any one of the peaks is fine.` Thus, we can just **use BinarySearch to shrink confirmed searching region** iterately and finally get the result. 20 | 21 | > In a nutshell, Binary Search can be applied to the following 2 senarios. 22 | > 23 | > 1. find a target element in a sorted array. 24 | > 25 | > 2. there is a function f(x), find a (the first) element x such that f(x) is true. 26 | 27 | 28 | --- 29 | Reference Link: [问一个关于binary search循环跳出条件的问题](http://www.1point3acres.com/bbs/forum.php?mod=redirect&goto=findpost&ptid=161799&pid=2139522&fromuid=96813) -------------------------------------------------------------------------------- /Pascal Triangle.md: -------------------------------------------------------------------------------- 1 | # Pascal Triangle 2 | 3 | ## [Pascal Triangle II](https://leetcode.com/problems/pascals-triangle-ii/) 4 | 5 | I think most people are familiar with Pascal Triangles and it might be easy for most people to construct it from row\_0 to row\_n. But this problem gives us an insight on how to construct *a single line* of Pascal Triangle `with only O(n) space`. 6 | 7 | ```java 8 | public List getRow(int rowIndex) { 9 | Integer[] res = new Integer[rowIndex + 1]; 10 | Arrays.fill(res,1); 11 | for(int row=0;row0;col--) 13 | res[col]+=res[col-1]; 14 | return Arrays.asList(res); 15 | } 16 | ``` 17 | 18 | Here is a picture version explanation to the solution above. Writing down each step on the paper, We can see that we are actually constructing the traigle in-place! 19 | 20 |
21 | pascal 22 |
23 | 24 | *NOTE: we must construct the line from right to left to assure that the value we used is calculated during last iteration/line (not the current one).* 25 | 26 | Another version of code based on similar thought: 27 | 28 | ```java 29 | public List getRow(int rowIndex) { 30 | List ret = new ArrayList(); 31 | ret.add(1); 32 | for (int i = 1; i <= rowIndex; i++) { 33 | for (int j = i - 1; j >= 1; j--) { 34 | int tmp = ret.get(j - 1) + ret.get(j); 35 | ret.set(j, tmp); 36 | } 37 | ret.add(1); 38 | } 39 | return ret; 40 | } 41 | ``` -------------------------------------------------------------------------------- /Problems with Math Solutions.md: -------------------------------------------------------------------------------- 1 | # Problems with Math Solutions 2 | 3 | ## [Gray Code](https://leetcode.com/problems/gray-code/) 4 | 5 | The idea is simple. G(i) = i^ (i/2). See more details in [WIKIPEDIA](https://en.wikipedia.org/wiki/Gray_code). 6 | 7 | ```java 8 | public List grayCode(int n) { 9 | List res=new ArrayList<>(); 10 | for(int i=0;i<(1<>1); 12 | return res; 13 | } 14 | ``` 15 | 16 | ## [Rotate Function](https://leetcode.com/problems/rotate-function/) 17 | 18 | We can see at first glance that this problem give us a formula of F(n) and Bk[n]. This immediately let us realize that maybe a math solution is suitable for this problem. 19 | 20 | Write down and observe F(0) to F(n). 21 | 22 | ``` 23 | F(k) = 0*Bk[0] + 1*Bk[1] + ... + (n-1)*Bk[n-1] 24 | F(k-1) = 0*Bk-1[0] + 1*Bk-1[1] + ... + (n-1)*Bk-1[n-1] 25 | = 0*Bk[1] + 1*Bk[2] + ... + (n-2)*Bk[n-1] + (n-1)*Bk[0] 26 | ``` 27 | It turns out that: 28 | 29 | ``` 30 | F(k) - F(k-1) = Bk[1] + Bk[2] + ... + Bk[n-1] + (1-n)Bk[0] 31 | = (Bk[0] + ... + Bk[n-1]) - nBk[0] 32 | = sum - nBk[0] 33 | ``` 34 | 35 | Then, 36 | 37 | ``` 38 | F(k) = F(k-1) + sum - nBk[0] 39 | ``` 40 | So, What is Bk[0]? 41 | 42 | ``` 43 | k = 0; B[0] = A[0]; 44 | k = 1; B[0] = A[len-1]; 45 | k = 2; B[0] = A[len-2]; 46 | ... 47 | ``` 48 | Thus, we can write down our solution easily. 49 | 50 | ```java 51 | public int maxRotateFunction(int[] A) { 52 | int f=0,sum=0; 53 | for(int i=0;i=1;i--){ 59 | f=f+sum-A.length*A[i]; 60 | max=Math.max(max,f); 61 | } 62 | return max; 63 | } 64 | ``` -------------------------------------------------------------------------------- /Contains Duplicate.md: -------------------------------------------------------------------------------- 1 | # Contains Duplicate 2 | 3 | ## [Contains Duplicate I](https://leetcode.com/problems/contains-duplicate/) 4 | 5 | ```java 6 | public boolean containsDuplicate(int[] nums) { 7 | Set res=new HashSet<>(); 8 | for(int n:nums) 9 | if(!res.add(n)) return true; 10 | return false; 11 | } 12 | ``` 13 | 14 | The logic is simple. But, 15 | 16 | *NOTICE that we used `if(!res.add(n))` to check whether the 'n' is already in the set instead of `set.contains(n)`.* 17 | 18 | Because **`res.add(n)` returns a `boolean` type, it would get a slight performance improvement over using `set.contains()`.** 19 | 20 | > As a bonus in `Java 8`, using streams is O(n). For those who are not familiar with Java 8, please refer to [this Chinese webpage](http://ifeve.com/stream/), or you can google it yourself. 21 | 22 | ```java 23 | public boolean containsDuplicate(int[] nums) { 24 | Set seen = new HashSet<>(); 25 | return Arrays.stream(nums).anyMatch(num -> !seen.add(num)); 26 | } 27 | ``` 28 | A more concise version is to only use the following line of code. But it gets a TLE error in Leetcode. And I can't find out the reason yet. T_T 29 | `return nums.length != Arrays.stream(nums).distinct().count();` 30 | 31 | 32 | ## [Contains Duplicate II](https://leetcode.com/problems/contains-duplicate-ii/) 33 | 34 | A less efficient way is to use HashMap. 35 | 36 | But here we just use a HashSet and a sliding window. It is the `sliding window` logic that is more space efficient than plain hash map method. Running time complexity is similar anyways. 37 | 38 | ```java 39 | public boolean containsNearbyDuplicate(int[] nums, int k) { 40 | //sliding window 41 | Set set=new HashSet(); 42 | for(int i=0;ik) set.remove(nums[i-k-1]);//magic as it is. 44 | if(!set.add(nums[i])) return true; 45 | } 46 | return false; 47 | } 48 | ``` 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /LinkedList with Fast & Slow Pointers.md: -------------------------------------------------------------------------------- 1 | # LinkedList with Fast & Slow Pointers 2 | 3 | ## [Rotate List](https://leetcode.com/problems/rotate-list/) 4 | 5 | This problem is not tricky. A quick think leads us to use `fast & slow pointers`. 6 | 7 | **1.fast & slow pointers** 8 | 9 | ```java 10 | public ListNode rotateRight(ListNode head, int k) { 11 | if(head==null) return null; 12 | ListNode fast=head,slow=head; 13 | int size=1;//since we are already at head node 14 | while(fast.next!=null){ 15 | fast=fast.next; 16 | size++; 17 | } 18 | for(int i=0;i When we are writing Binary Search, we should: 8 | > 9 | > 1. **Guaruntee that the target element is always in [left,right] when shrinking the region**. Then write down the left and right border of the region. (In other words, whether to use mid+-1 or mid as the new left/right border.) 10 | > 11 | > 2. Determine how to calculate `mid` based on how we shrinked our searching region. **If we wrote `left=mid` then we should use `mid=left+(right-left+1)/2`, otherwise `mid=left+(right-left)/2`.** (Since the later 'mid' rounds down to the left border. When `right=left+1`, `left` itself equals to `mid`. So if we previously wrote `left=mid`, the region wouldn't shrink in this step.) 12 | > 13 | > 3. Loop termination condition would be either `left 15 | > 4. The inner-loop returning statement should always be `return mid`. Returning statement outside the loop should always be `return left`. 16 | 17 | A simple example: [First Bad Version](https://leetcode.com/problems/first-bad-version/) 18 | 19 | ```java 20 | public int firstBadVersion(int n) { 21 | int low=1,high=n; 22 | while(low prices[i - 1]) { 14 | maxProfit = Math.max(maxProfit, prices[i] - minPrice); 15 | } else { 16 | minPrice = Math.min(minPrice, prices[i]); 17 | } 18 | } 19 | 20 | return maxProfit; 21 | } 22 | ``` 23 | 24 | The second solution makes sense when the interviewer twists the question slightly by giving the difference array of prices. 25 | 26 | >Ex: for {1, 7, 4, 11}, if he gives {0, 6, -3, 7}, you might end up being confused. 27 | 28 | Here, the logic is to calculate the difference (maxCur += prices[i] - prices[i-1]) of the original array, and find a contiguous subarray giving maximum profit. If the difference falls below 0, reset it to zero. 29 | 30 | `maxCur = current maximum value` 31 | 32 | `maxSoFar = maximum value found so far` 33 | 34 | ```java 35 | public int maxProfit(int[] prices) { 36 | int maxCur=0,maxSoFar=0; 37 | for(int i=1;i Why do the two pointers must meet together when there is a cycle? 8 | >

9 | > The `fast` pointer first step into the cycle. When the `slow` pointer step into it, imagine that `slow` is in front of `fast` inside the cycle, and `fast` moves one step faster than `slow`/one step closer to `slow` each time. So they must meet at some time or there is no possibility that `fast` could jump over `slow`. 10 | 11 | ```java 12 | public boolean hasCycle(ListNode head) { 13 | if (head == null) return false; 14 | ListNode fast = head, slow = head; 15 | while (fast.next != null && fast.next.next != null) { 16 | slow = slow.next; 17 | fast = fast.next.next; 18 | if (fast == slow) return true; 19 | } 20 | return false; 21 | } 22 | ``` 23 | 24 | This problem has many [follow-up questions](http://www.cnblogs.com/hiddenfox/p/3408931.html). Here's some versions of them. 25 | 26 | **1. what is the length of the cycle?** 27 | 28 | 29 | 30 | In this picture, let's say X is the 1st node of list, Y is the 1st node in the cycle, Z is the node where `slow` and `fast` meet at the first time. 31 | 32 | ***Solution 1 (most simple)*** 33 | 34 | Since `fast` moves twice as fast as `slow`, then we have `2(a+b)=a+b+c+b`, namely, `a=c`. 35 | 36 | Thus, `the length of cycle = a+b`. That is to say, the iteration time from the 1st node in the list X to the 1st node Y where they met is equal to the length of the cycle. 37 | 38 | ***Solution 2*** 39 | 40 | Let `slow` and `fast` continue to move after their first meet. Record the iteration times from their first meet to their second meet, and this is going to be exactly the length of the cycle. 41 | 42 | ***Solution 2*** 43 | 44 | Let `slow` continue to move after their first meet and let `fast` stay there. Record the iteration times from their first meet to their second meet, and this is going to be exactly the length of the cycle. 45 | 46 | 47 | **2. how to find the 1st node of the cycle(See `@Linked List Cycle II` )?** 48 | 49 | ## [Linked List Cycle II](https://leetcode.com/problems/linked-list-cycle-ii/) 50 | 51 | ```java 52 | public ListNode detectCycle(ListNode head) { 53 | if (head == null) return null; 54 | boolean hasCycle = false; 55 | ListNode fast = head, slow = head; 56 | while (fast.next != null && fast.next.next != null) { 57 | fast = fast.next.next; 58 | slow = slow.next; 59 | if (slow == fast) { 60 | hasCycle = true; 61 | break; 62 | } 63 | } 64 | 65 | if (hasCycle == false) return null; 66 | slow = head; 67 | while (slow != fast) { 68 | slow = slow.next; 69 | fast = fast.next; 70 | } 71 | return fast; 72 | } 73 | ``` 74 | 75 | 76 | -------------------------------------------------------------------------------- /Dynamic Programming-1D.md: -------------------------------------------------------------------------------- 1 | # Dynamic Programming-1D 2 | 3 | ## [Triangle](https://leetcode.com/problems/triangle/) 4 | 5 | > thoughs and ideas are borrowed from [this post by stellari](https://discuss.leetcode.com/topic/1669/dp-solution-for-triangle). 6 | 7 | The traingle has a tree like tructure, which would lead us think about traversal algorithm DFS. However, if you look closely, you would notice that the ajacent nodes always share a branch. In other words, there are **`overlapping subproblems`** in this problem. Meanwhile, suppose p,q are children of x, once the min path from p,q to the bottom is known, the min path starting from x can be calculated in O(1). That is **`optimal substructure`**. Therefore, **DP is the best solution to this problem in terms of time complexity.** 8 | 9 | > Bottom-up or Top-down ? 10 | >

11 | > **For 'top-down' DP**, starting from the node on the very top, we recursively find the minimum path sum of each node. When a path sum is calculated, we store it in an array (`memoization`); the next time we need to calculate the path sum of the same node, just retrieve it from the array. 12 | > 13 | > However, you will need a cache that is at least the same size as the input triangle itself to store the pathsum, which takes `O(n^2) space`. With some clever thinking, it might be possible to release some of the memory that will never be used after a particular point, but the order of the nodes being processed is not straightforwardly seen in a recursive solution, so deciding which part of the cache to discard can be a hard job. 14 | >

15 | > **For 'Bottom-up' DP**, on the other hand, is very straightforward: we start from the nodes on the bottom row; the min pathsums for these nodes are the values of the nodes themselves. From there, the min pathsum at the ith node on the kth row would be the lesser of the pathsums of its two children plus the value of itself, i.e.: 16 | > 17 | `OPT(i,j) = min( OPT(i+1,j) , OPT(i+1,j+1) ) + triangle[i][j]` 18 | > Since OPT(i+1,?) would be useless after calculating OPT(i,?) is computed, we can simply set OPT(i,j) as a 1D array OPT(i), and iteratively update itself: 19 | > 20 | > `OPT(j) = min( OPT(j) , OPT(j+1) ) + triangle[i][j]` 21 | 22 | Bottom-up 23 | 24 | ```java 25 | public int minimumTotal(List> triangle) { 26 | //bottom-up 27 | int[] dp=new int[triangle.size()]; 28 | for(int i=0;i=0;i--) 32 | for(int j=0;j<=i;j++) 33 | dp[j]=Math.min(dp[j],dp[j+1])+triangle.get(i).get(j); 34 | return dp[0]; 35 | } 36 | ``` 37 | 38 | Top-down 39 | 40 | ```java 41 | public int minimumTotal(List> triangle) { 42 | int rowNum = triangle.get(triangle.size() - 1).size(); 43 | int colNum = triangle.size(); 44 | int[][] dp = new int[rowNum][colNum]; 45 | int i = 0; 46 | for (Integer n : triangle.get(colNum - 1)) { 47 | dp[rowNum - 1][i++] = n; 48 | } 49 | for (int row = rowNum - 2, m = 0; row >= 0; row--, m++) { 50 | for (int col = 0; col <= colNum - 2 - m; col++) { 51 | dp[row][col] = Math.min(dp[row + 1][col], dp[row + 1][col + 1]) 52 | + triangle.get(row).get(col); 53 | } 54 | } 55 | return dp[0][0]; 56 | } 57 | ``` 58 | -------------------------------------------------------------------------------- /Heap.md: -------------------------------------------------------------------------------- 1 | # Heap 2 | 3 | ## [K-th Smallest Element in a Sorted Matrix](https://leetcode.com/problems/kth-smallest-element-in-a-sorted-matrix/) 4 | 5 | Inspired by [this post](https://discuss.leetcode.com/topic/52948/share-my-thoughts-and-clean-java-code), the following problem in my class CSCI 570 came to my mind. 6 | 7 | > In the MERGE-SORT algorithm we merge two sorted lists into one sorted list in O(n) time. Describe an O(n log k)-time algorithm to merge k sorted lists into one sorted list, where n is the total number of elements in all the input lists. Be sure to explain why your algorithm runs in O(n log k)-time. 8 | >

9 | > **SOLUTION:** 10 | > 11 | > First we remove the smallest element from each sorted list and we build a min-priority queue (using a min-heap) out of these elements in O(k) time. Then we repeat the following steps: we extract the minimum from the min-priority queue (in O(log k) time) and this will be the next element in the sorted order. From the original sorted list where this element came from we remove the next smallest element (if it exists) and insert it to the min-priority queue (in O(log k) time) . We are done when the queue becomes empty and at this point we have all the numbers in our sorted list. The total running time is O(k + n log k) = O(n log k). 12 | 13 | I think this leetcode problem is a variant of the problem above. 14 | 15 | Similarly, we can use a min-heap implemented by `PriorityQueue`(PQ). In detail, we need a Data Structure `Tuple` to store elements, which contains the row/column number and value of the element. 16 | 17 | First we insert all `Tuples` in the 1st row to the heap. Then repeat the following steps `k-1` times: 18 | 19 | 1.Extract the min element in PQ. 20 | 21 | 2.From the original `row` in sorted matrix where this element came from we remove the next element (if it exists) and insert it to PQ. 22 | 23 | Return the element we found. 24 | 25 | ```java 26 | public int kthSmallest(int[][] matrix, int k) { 27 | PriorityQueue pq=new PriorityQueue<>(); 28 | for(int i=0;i{ 38 | int i,j,val; 39 | public Tuple(int i,int j,int val){ 40 | this.i=i; 41 | this.j=j; 42 | this.val=val; 43 | } 44 | public int compareTo(Tuple that){ 45 | return this.val-that.val; 46 | } 47 | } 48 | ``` 49 | 50 | TIPS: Pay attention that (from [Java API](http://docs.oracle.com/javase/8/docs/api/java/util/PriorityQueue.html)) 51 | 52 | >the elements of `PriorityQueue` data structure are ordered according to their `natural ordering`, or by a `Comparator` provided at queue construction time, depending on which constructor is used. A priority queue does not permit null elements. A priority queue relying on natural ordering also does not permit insertion of non-comparable objects (doing so may result in ClassCastException). 53 | 54 | ALSO, 'The head of this queue is the least element with respect to the specified ordering.' This means that whether the heap is a minHeap or maxHeap depends on the `ordering` we defined in `Comparable` or `Comparator`. 55 | 56 | 57 | ## [Find K Pairs with Smallest Sums](https://leetcode.com/problems/find-k-pairs-with-smallest-sums/) 58 | 59 | Similar as the first problem. 60 | 61 | 62 | ```java 63 | public List kSmallestPairs(int[] nums1, int[] nums2, int k) { 64 | PriorityQueue pq=new PriorityQueue<>(); 65 | List res=new ArrayList<>(); 66 | if(nums1 == null || nums1.length == 0 || nums2 == null || nums2.length == 0 || k <= 0) return res; 67 | for(int i=0;i{ 78 | int i1,i2,val; 79 | public Tuple(int i1,int i2,int val){ 80 | this.i1=i1; 81 | this.i2=i2; 82 | this.val=val; 83 | } 84 | public int compareTo(Tuple that){ 85 | return this.val-that.val; 86 | } 87 | } 88 | ``` 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /Kth Smallest Element in a BST: -------------------------------------------------------------------------------- 1 | # [Kth Smallest Element in a BST](https://leetcode.com/problems/kth-smallest-element-in-a-bst/) 2 | 3 | The in-order traversal of a BST outputs the nodes in sorted order. So we can just do inorder traversal and check for the `k-th` node. 4 | 5 | Time: O(n), Space: O(n) 6 | 7 | **In-order Traversal - Recursion** 8 | 9 | ```java 10 | private int count=0; 11 | private int res=Integer.MIN_VALUE; 12 | public int kthSmallest(TreeNode root, int k) { 13 | traverse(root,k); 14 | return res; 15 | } 16 | private void traverse(TreeNode node,int k){ 17 | if(node==null) return; 18 | traverse(node.left,k); 19 | count++; 20 | if(count==k) res=node.val; 21 | if(count stack=new Stack<>(); 29 | TreeNode node=root; 30 | int count=0; 31 | while(!stack.empty()||node!=null){ 32 | if(node!=null){ 33 | stack.push(node); 34 | node=node.left; 35 | }else{ 36 | if((++count)==k) return stack.peek().val;//NOTE:not count++!!! 37 | node=stack.pop().right; 38 | } 39 | } 40 | return Integer.MIN_VALUE; 41 | } 42 | ``` 43 | 44 | > **Follow up:** 45 | > 46 | > What if the BST is modified (insert/delete operations) often and you need to find the kth smallest frequently? How would you optimize the kthSmallest routine? 47 | > 48 | > **Hint:** 49 | > 50 | > Try to utilize the property of a BST. 51 | > 52 | > What if you could modify the BST node's structure? 53 | > 54 | > The optimal runtime complexity is O(height of BST). 55 | 56 | We can ***augment the BST tree structure*** to have each node in it store the number of elements in its left subtree. With this piece of information, it is simple to traverse the tree by repeatedly asking for the number of elements in the left subtree, to decide whether to do recurse into the left or right subtree. 57 | 58 | Now, suppose we are at node T: 59 | 60 | 1. If k == num_elements(left subtree of T)-1, then the answer we're looking for is the value in node T. 61 | 2. If k >= num_elements(left subtree of T), then obviously we can ignore the left subtree, because those elements will also be smaller than the kth smallest. So, we reduce the problem to finding the k - num_elements(left subtree of T) smallest element of the right subtree. 62 | 3. If k < num_elements(left subtree of T)-1, then the kth smallest is somewhere in the left subtree, so we reduce the problem to finding the kth smallest element in the left subtree. 63 | 64 | ***Complexity analysis*** 65 | 66 | Time: O(n) + **O(nlogn)** 67 | 68 | If we could add a count field in the BST node class, it will take O(n) time when we calculate the count value for the whole tree, ***but after that, it will take O(logn) time when insert/delete a node or calculate the kth smallest element.*** 69 | 70 | ```java 71 | public int kthSmallest(TreeNode root, int k) { 72 | TreeNodeWithCount rootWithCount=buildTreeWithCount(root); 73 | return kthSmallest(rootWithCount, k); 74 | } 75 | 76 | private TreeNodeWithCount buildTreeWithCount(TreeNode root) { 77 | if (root==null) return null; 78 | TreeNodeWithCount rootWithCount=new TreeNodeWithCount(root.val); 79 | rootWithCount.left=buildTreeWithCount(root.left); 80 | rootWithCount.right=buildTreeWithCount(root.right); 81 | if (rootWithCount.left !=null) rootWithCount.count +=rootWithCount.left.count; 82 | if (rootWithCount.right !=null) rootWithCount.count +=rootWithCount.right.count; 83 | return rootWithCount; 84 | } 85 | 86 | private int kthSmallest(TreeNodeWithCount rootWithCount, int k) { 87 | if (k <=0 || k > rootWithCount.count) return -1; 88 | if (rootWithCount.left !=null) { 89 | if (rootWithCount.left.count >=k) return kthSmallest(rootWithCount.left, k); 90 | if (rootWithCount.left.count==k-1) return rootWithCount.val; 91 | return kthSmallest(rootWithCount.right, k-1-rootWithCount.left.count); 92 | } 93 | else { 94 | if (k==1) return rootWithCount.val; 95 | return kthSmallest(rootWithCount.right, k-1); 96 | } 97 | } 98 | 99 | class TreeNodeWithCount { 100 | int val; 101 | int count; 102 | TreeNodeWithCount left; 103 | TreeNodeWithCount right; 104 | TreeNodeWithCount(int x) { 105 | val=x; 106 | count=1; 107 | } 108 | } 109 | ``` 110 | 111 | 112 | NOTICE: DO NOT RECORD THE ORDER DIRECTLY (the order of current element, i.e. # of element in left subtree+1) 113 | 114 | What you stored in TreeNodeWithCount is the order of its value, not the count of its children. So you will not achieve the target which takes O(logn) time when insert/delete a node or calculate the kth smallest element after. 115 | For example, if a number less than the min value of the BST inserted, you will have to change the order of all the nodes. This will cost O(n) time, not O(logn); -------------------------------------------------------------------------------- /rotation.md: -------------------------------------------------------------------------------- 1 | # Rotation 2 | 3 | There are several ways to deal with `String Rotation`. Now we will talk about them. 4 | 5 | ## [Rotate Array](https://leetcode.com/problems/rotate-array/) 6 | 7 | **1.Use extra copy** 8 | 9 | Time: O(n). Space:O(n). 10 | 11 | ```java 12 | public void rotate(int[] nums, int k) { 13 | int[] tmp=new int[nums.length]; 14 | for(int i=0;i0;j--)//rotate one by one 31 | nums[j]=nums[j-1]; 32 | nums[0]=tmp; 33 | } 34 | } 35 | ``` 36 | 37 | **3.3 reverse thinking** 38 | 39 | Time:O(n). Space:O(1) 40 | 41 | ```java 42 | public void rotate(int[] nums, int k) { 43 | k%=nums.length; 44 | reverse(nums,0,nums.length-1); 45 | reverse(nums,0,k-1); 46 | reverse(nums,k,nums.length-1); 47 | } 48 | 49 | private void reverse(int[] nums,int start,int end){ 50 | while(start GeeksforGeeks: 63 | 64 | This is an extension of `solution 2`. Instead of moving one by one, divide the array in different sets 65 | where number of sets is equal to GCD of n and d and move the elements within sets. 66 | 67 | If GCD is 1 as is for the above example array (n = 7 and d =2), then elements will be moved within one set only, we just start with temp = arr[0] and keep moving arr[I+d] to arr[I] and finally store temp at the right place. 68 | 69 | Here is an example for n =12 and d = 3. GCD is 3 and 70 |
jumping
71 | 72 | *You can read my tips first: 73 | [XOR Swapping Algorithm](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/XOR%20Swapping%20Method.md) | 74 | [GCD](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/GCD.md)* 75 | 76 | ```java 77 | public void rotate(int[] nums, int k) { 78 | k%=nums.length; 79 | int gcd=gcd(nums.length,k); 80 | for(int i=0;i GCD = gcd(3,8) = 1, which means there is only one path. 103 | > Count = (n / GCD) - 1 = 7, which means we need 7 swaps to finish the path. (actually for a path have x element, we need x - 1 swaps). 104 | > 105 | > Then we can simulate the process of the algorithm, 106 | > path0(each time swap index0 element and indexPosition element): [1,2,3,4,5,6,7,8]
107 | > position = 3 -> [4,2,3,1,5,6,7,8]
108 | > position = 6 -> [7,2,3,1,5,6,4,8]
109 | > position = 1 -> [2,7,3,1,5,6,4,8]
110 | > position = 4 -> [5,7,3,1,2,6,4,8]
111 | > position = 7 -> [8,7,3,1,2,6,4,5]
112 | > position = 2 -> [3,7,8,1,2,6,4,5]
113 | > position = 5 -> [6,7,8,1,2,3,4,5] -> finished, total 7 times swap.
114 | > Final result [6,7,8,1,2,3,4,5] 115 | 116 | - suppose k = 2: 117 | 118 | > Similary, GCD = 2, which means there are 2 paths. count = 3, which means we need 3 swaps to finish each path. 119 | > 120 | > Give the process:
121 | > path0(swap index0 and position element):[1,2,3,4,5,6,7,8]
122 | > position = 2 -> [3,2,1,4,5,6,7,8]
123 | > position = 4 -> [5,2,1,4,3,6,7,8]
124 | > position = 6 -> [7,2,1,4,3,6,5,8] -> path0 finished 125 | > 126 | > Then we continue processing path1(swap index1 and position element):[7,2,1,4,3,6,5,8]
127 | > position = 3 -> [7,4,1,2,3,6,5,8]
128 | > position = 5 -> [7,6,1,2,3,4,5,8]
129 | > position = 7 ->[7,8,1,2,3,4,5,6] -> path1 finished -> all path finished we get the result [7,8,1,2,3,4,5,6] 130 | 131 | *NOTE: This algorithm is very similar to the `juggling algorithm` proposed in 'Programming Perl'. Some related links to help understand are as follows. 132 | [http://www.geeksforgeeks.org/array-rotation/](http://www.geeksforgeeks.org/array-rotation/)
133 | [http://stackoverflow.com/questions/23321216/rotating-an-array-using-juggling-algorithm](http://stackoverflow.com/questions/23321216/rotating-an-array-using-juggling-algorithm)* 134 | -------------------------------------------------------------------------------- /Tree Traversal.md: -------------------------------------------------------------------------------- 1 | # Tree Traversal 2 | 3 | ## [Binary Tree Preorder Traversal](https://leetcode.com/problems/binary-tree-preorder-traversal/) 4 | 5 | **Preorder** 6 | 7 | root->left subtree->right subtree 8 | 9 | **1.recursion** 10 | 11 | ```java 12 | public List preorderTraversal(TreeNode root) { 13 | List res=new ArrayList<>(); 14 | if(root==null) return res; 15 | res.add(root.val); 16 | res.addAll(preorderTraversal(root.left)); 17 | res.addAll(preorderTraversal(root.right)); 18 | return res; 19 | } 20 | ``` 21 | 22 | **2.iteration** 23 | 24 | ```java 25 | public List preorderTraversal(TreeNode root) { 26 | List res=new LinkedList<>(); 27 | Stack stack=new Stack<>(); 28 | stack.push(root); 29 | while(!stack.empty()){ 30 | TreeNode node=stack.pop(); 31 | if(node!=null){ 32 | res.add(node.val); 33 | stack.push(node.right); 34 | stack.push(node.left); 35 | } 36 | } 37 | return res; 38 | } 39 | ``` 40 | 41 | ## [Binary Tree Inorder Traversal](https://leetcode.com/problems/binary-tree-inorder-traversal/) 42 | 43 | **1.recursion** 44 | 45 | ```java 46 | public List inorderTraversal(TreeNode root) { 47 | List res=new ArrayList<>(); 48 | if(root==null) return res; 49 | res.addAll(inorderTraversal(root.left)); 50 | root.add(root.val); 51 | root.addAll(inorderTraversal(root.right)); 52 | return res; 53 | } 54 | ``` 55 | 56 | **2.iteration** 57 | 58 | ```java 59 | public List inorderTraversal(TreeNode root) { 60 | List res=new LinkedList<>(); 61 | Stack stack=new Stack<>(); 62 | while(root!=null||!stack.empty()){ 63 | while(root!=null){ 64 | stack.push(root); 65 | root=root.left; 66 | } 67 | root=stack.pop(); 68 | res.add(root.val); 69 | root=root.right; 70 | } 71 | return res; 72 | } 73 | ``` 74 | 75 | ## [Binary Tree Postorder Traversal](https://leetcode.com/problems/binary-tree-postorder-traversal/) 76 | 77 | **1.iteration** 78 | 79 | ```java 80 | public List postorderTraversal(TreeNode root) { 81 | List res = new LinkedList(); 82 | Stack stack=new Stack(); 83 | TreeNode prev=null; 84 | while(root!=null||!stack.empty()) 85 | if(root!=null){ 86 | stack.push(root); 87 | root=root.left; 88 | }else{ 89 | TreeNode tmp=stack.peek(); 90 | if(tmp.right!=null&&tmp.right!=prev) root=tmp.right; 91 | else{ 92 | stack.pop(); 93 | res.add(tmp.val); 94 | prev=tmp; 95 | } 96 | } 97 | return res; 98 | } 99 | ``` 100 | 101 | **2.recursion** 102 | 103 | ```java 104 | public List postorderTraversal(TreeNode root) { 105 | List res = new LinkedList(); 106 | if(root==null) return res; 107 | res.addAll(postorderTraversal(root.left)); 108 | res.addAll(postorderTraversal(root.right)); 109 | res.add(root.val); 110 | return res; 111 | } 112 | ``` 113 | 114 | ## [Binary Tree Level Order Traversal](https://leetcode.com/problems/binary-tree-level-order-traversal/) 115 | 116 | ```java 117 | public List> levelOrder(TreeNode root) { 118 | List> res=new ArrayList<>(); 119 | Queue queue=new LinkedList<>(); 120 | if(root==null) return res; 121 | queue.offer(root); 122 | while(!queue.isEmpty()){ 123 | List list=new ArrayList<>(); 124 | int size=queue.size(); 125 | for(int i=0;i(list)); 132 | } 133 | return res; 134 | } 135 | ``` 136 | 137 | ## [Binary Tree Zigzag Level Order Traversal](https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/) 138 | 139 | ```java 140 | public List> zigzagLevelOrder(TreeNode root) { 141 | List> res=new ArrayList<>(); 142 | Queue queue=new LinkedList<>(); 143 | if(root==null) return res; 144 | queue.add(root); 145 | int level=1; 146 | while(!queue.isEmpty()){ 147 | int size=queue.size();//necessary, cause queue size would be modified later. 148 | List list=new ArrayList<>(); 149 | for(int i=0;i(list)); 158 | } 159 | return res; 160 | } 161 | ``` 162 | 163 | -------------------------------------------------------------------------------- /Stack.md: -------------------------------------------------------------------------------- 1 | # Stack 2 | 3 | ## [Mini Parser](https://leetcode.com/problems/mini-parser/) 4 | 5 | I think the most important point of this problem is to read the instruction carefully and make sure you've understood it. 6 | 7 | Here is part of the instruction: 8 | 9 | > **Example 1:** Given s = "324", 10 | > 11 | > You should return a NestedInteger object which contains a single integer 324. 12 | > 13 | > **Example 2:** 14 | > Given s = "[123,[456,[789]]]", 15 | > 16 | > Return a NestedInteger object containing a nested list with 2 elements: 17 | > 18 | >    An integer containing value 123. 19 | > 20 | >    A nested list containing two elements: 21 | > 22 | >       i. An integer containing value 456. 23 | > 24 | >       ii. A nested list with one element: 25 | > 26 | >          An integer containing value 789. 27 | 28 | Take a careful look at these two examples, you can find that: 29 | 30 | iterate through the input string, 31 | 32 | whenever we encounter a `"["`, create a list and push it into stack. Then set the `start` point to i+1. 33 | 34 | whenever we encounter a `","` or `"]"`, 35 | 36 |    if `i getList(); 69 | * } 70 | */ 71 | public NestedInteger deserialize(String s) { 72 | if(!s.startsWith("[")) 73 | return new NestedInteger(Integer.valueOf(s)); 74 | Stack stack=new Stack<>(); 75 | NestedInteger res=new NestedInteger(); 76 | stack.push(res);//push empty 'res' list to stack 77 | int start=1;//to keep track of the next begin index of a new single NestedInteger 78 | for(int i=1;i list; 104 | private Integer integer; 105 | 106 | public NestedInteger(List list){ 107 | this.list = list; 108 | } 109 | 110 | public void add(NestedInteger nestedInteger) { 111 | if(this.list != null){ 112 | this.list.add(nestedInteger); 113 | } else { 114 | this.list = new ArrayList(); 115 | this.list.add(nestedInteger); 116 | } 117 | } 118 | 119 | public void setInteger(int num) { 120 | this.integer = num; 121 | } 122 | 123 | public NestedInteger(Integer integer){ 124 | this.integer = integer; 125 | } 126 | 127 | public NestedInteger() { 128 | this.list = new ArrayList(); 129 | } 130 | 131 | public boolean isInteger() { 132 | return integer != null; 133 | } 134 | 135 | public Integer getInteger() { 136 | return integer; 137 | } 138 | 139 | public List getList() { 140 | return list; 141 | } 142 | 143 | public String printNi(NestedInteger thisNi, StringBuilder sb){ 144 | if(thisNi.isInteger()) { 145 | sb.append(thisNi.integer); 146 | sb.append(","); 147 | } 148 | sb.append("["); 149 | for(NestedInteger ni : thisNi.list){ 150 | if(ni.isInteger()) { 151 | sb.append(ni.integer); 152 | sb.append(","); 153 | } 154 | else { 155 | printNi(ni, sb); 156 | } 157 | } 158 | sb.append("]"); 159 | return sb.toString(); 160 | } 161 | } 162 | ``` 163 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LeetCode-Summary 2 | 3 | ## General Methods & Tips 4 | 1. [Binary Search Coding Principles](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Binary%20Search%20Coding%20Principles.md) 5 | 2. [XOR Swapping Method](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/XOR%20Swapping%20Method.md) 6 | 3. [GCD](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/GCD.md) 7 | 8 | ## Catalog 9 | 10 | ### Array 11 | 12 | 1. [**k Sum**](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/k-Sum.md)
13 | [2 Sum](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/k-Sum.md#2-sum)--exactly one solution/no duplicates 14 | 15 | - HashMap:O(n) <=no duplicate 16 | - Sort+Two Pointers:O(nlogn); if sorted:O(n) 17 | 18 | [3 Sum](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/k-Sum.md#3-sum)-contains duplicates 19 | - Sort+Two Pointers:O(n^2) 20 | 21 | [3 Sum Closest](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/k-Sum.md#3-sum-closest) 22 | - Sort+Two Pointers:O(n^2), cannot use hashmap since it looks for the closest answer instead of the exact one. 23 | 24 | [4 Sum](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/k-Sum.md#4-sum) 25 | - Sort+Two Pointers:O(n^3),some modifications to avoid useless computations 26 | - 'Two Sum' solution:O(n^2*logn) 27 | 2. [**Rotation**](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/rotation.md)   -*to be continued*
28 | [Rotate Array](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/rotation.md#rotate-array)

29 | 3. [**Pascal's Triangle II**](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Pascal%20Triangle.md) 30 |

31 | 4. [**Contains Duplicate**](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Contains%20Duplicate.md) -**not finnished yet**
32 | [Contains Duplicate I](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Contains%20Duplicate.md#contains-duplicate-i)
33 | [Contains Duplicate II](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Contains%20Duplicate.md#contains-duplicate-ii)

34 | 5. [**Intersection of Two Arrays**](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Intersection%20of%20Two%20Arrays.md) -*to be continued*
35 | [Intersection of Two Arrays I](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Intersection%20of%20Two%20Arrays.md#intersection-of-two-arrays-i)
36 | 37 | ### String 38 | 39 | 1. [**String**](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/String.md) 40 | 41 | ### Math 42 | 43 | 1. [**Math Solutions**](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Problems%20with%20Math%20Solutions.md)
44 | [Gray Code](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Problems%20with%20Math%20Solutions.md#gray-code)
45 | [Rotate Function](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Problems%20with%20Math%20Solutions.md#rotate-function)

46 | 47 | ### LinkedList 48 | 49 | 1. [**Fast & Slow Pointers**](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/LinkedList%20with%20Fast%20%26%20Slow%20Pointers.md)
50 | [Rotate List](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/LinkedList%20with%20Fast%20%26%20Slow%20Pointers.md#rotate-list)

51 | 52 | ### Dynamic Programming 53 | 54 | 1. [**Best Time to Buy and Sell Stock**](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Best%20Time%20to%20Buy%20and%20Sell%20Stock.md) -*to be continued*
55 | [Best Time to Buy and Sell Stock](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Best%20Time%20to%20Buy%20and%20Sell%20Stock.md#best-time-to-buy-and-sell-stock-i)
56 | [Best Time to Buy and Sell Stock II](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Best%20Time%20to%20Buy%20and%20Sell%20Stock.md#best-time-to-buy-and-sell-stock-ii)
57 | [Best Time to Buy and Sell Stock with Cooldown](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Best%20Time%20to%20Buy%20and%20Sell%20Stock.md#best-time-to-buy-and-sell-stock-with-cooldown)
58 | 2. [**Majority Element**](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Majority%20Element.md)
59 | 3. [**Dynamic Programming - 2D**](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Dinamic%20Programming-2D.md) -*to be continued*
60 | [Minimum Path Sum](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Dinamic%20Programming-2D.md#minimum-path-sum) 61 | 62 | ### Binary Search 63 | 64 | 1. [**Find Peak Element**](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Find%20Peak%20Element.md) -*to be continued* 65 | 66 | ### Heap 67 | 68 | 1. [**Heap**](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Heap.md)
69 | [K-th Smallest Element in a Sorted Matrix](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Heap.md#k-th-smallest-element-in-a-sorted-matrix)
70 | [Find K Pairs with Smallest Sums](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Heap.md#find-k-pairs-with-smallest-sums) 71 | 72 | ### Backtracking 73 | 74 | 1. [**Classic Backtrackings**](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Classic%20Backtrackings.md)
75 | [Palindrome Partitioning](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Classic%20Backtrackings.md#palindrome-partitioning)
76 | [Combinations](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Classic%20Backtrackings.md#combinations)
77 | [Combination Sum](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Classic%20Backtrackings.md#combination-sum)
78 | [Combination Sum II](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Classic%20Backtrackings.md#combination-sum-ii)
79 | [Combination Sum III](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Classic%20Backtrackings.md#combination-sum-iii)
80 | [Permutation](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Classic%20Backtrackings.md#permutation)
81 | [Permutation II](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Classic%20Backtrackings.md#permutation-ii)
82 | [Subsets](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Classic%20Backtrackings.md#subsets)
83 | [Subsets II](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Classic%20Backtrackings.md#subsetsii) 84 | 85 | 2. [**Backtracking**](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Backtracking.md)
86 | [Generate Parentheses](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Backtracking.md#generate-parentheses)
87 | [Letter Combinations of a Phone Number](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Backtracking.md#letter-combinations-of-a-phone-number)
88 | [Binary Watch](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Backtracking.md#binary-watch)
89 | [Word Search](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Backtracking.md#word-search) 90 | 91 | ### Tree 92 | 93 | 1. [**Tree Traversal**](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Tree%20Traversal.md)
94 | [Binary Tree Preorder Traversal](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Tree%20Traversal.md#binary-tree-preorder-traversal)
95 | [Binary Tree Inorder Traversal](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Tree%20Traversal.md#binary-tree-inorder-traversal)
96 | [Binary Tree Postorder Traversal](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Tree%20Traversal.md#binary-tree-postorder-traversal)
97 | [Binary Tree Level Order Traversal](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Tree%20Traversal.md#binary-tree-level-order-traversal)
98 | [Binary Tree Zigzag Level Order Traversal](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Tree%20Traversal.md#binary-tree-zigzag-level-order-traversal)
99 | -------------------------------------------------------------------------------- /Backtracking.md: -------------------------------------------------------------------------------- 1 | # Backtracking 2 | 3 | > [Here are summary of some `classic Backtracking` problems](https://github.com/TongZhangUSC/LeetCode-Summary/blob/master/Classic%20Backtrackings.md) 4 | 5 | The followings are backtracking problem with more than one solution or with a few tricky points in it. 6 | 7 | ## [Generate Parentheses](https://leetcode.com/problems/generate-parentheses/) 8 | 9 | I was really inspired by [this post](http://www.1point3acres.com/bbs/forum.php?mod=redirect&goto=findpost&ptid=172641&pid=2237150&fromuid=96813). That guy summarized a general idea of `Backtracking`. I try to translate into English and add some supplemental materials. 10 | 11 | *WIKIPEDIA: Backtracking is a general algorithm for finding all (or some) solutions to some computational problems that incrementally builds candidates to the solutions, and abandons each partial candidate c ("backtracks") as soon as it determines that c cannot possibly be completed to a valid solution.* 12 | 13 | >The basic thought is that: You have many options under current senario and choose one of them each time. You must fall into the following two cases-either you find this option, violating some restraints, is invalid and abandon it or it is valid in the end and you add it to the solution. 14 | > 15 | >So, whenever you are thinking about `backtracking`, you only need to consider three things: OPTIONS, RESTRAINTS and TERMINATION. 16 | 17 | In this problem, you always have two options: 18 | 19 | 1. add left parenthese 20 | 2. add left parenthese 21 | 22 | And you always have these restraints: 23 | 24 | 1. if the number of left parentheses is equal to n, then you can't add left parentheses any more. 25 | 2. if the number of left parentheses is equal to number of right parentheses, then you can't add right parentheses any more. 26 | 27 | The termination is: 28 | All left and right parentheses are used up. This must be the correct solution and you can add it to the result set. 29 | 30 | Here is the code. 31 | 32 | ```java 33 | public List generateParenthesis(int n) { 34 | int left=0,right=0; 35 | List res=new ArrayList<>(); 36 | backtracking(res,"",0,0,n); 37 | return res; 38 | } 39 | private void backtracking(List res,String p,int left,int right,int n){ 40 | if(left==n&&right==n){ 41 | res.add(p); 42 | return; 43 | } 44 | if(left letterCombinations(String digits) { 67 | List res=new ArrayList<>(); 68 | if(digits.length()==0) return res; 69 | String[] map={"0","1","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"}; 70 | backtracking(res,digits,map,"",0); 71 | return res; 72 | } 73 | private void backtracking(List res,String digits,String[] map,String s,int start){ 74 | if(start==digits.length()){ 75 | res.add(s); 76 | return; 77 | } 78 | for(int i=0;i letterCombinations(String digits) { 90 | LinkedList res=new LinkedList<>();//List会返回peek未定义 91 | if(digits.length()==0) return res; 92 | String[] map={"0","1","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"}; 93 | res.add(""); 94 | for(int i=0;i readBinaryWatch(int num) { 112 | //countbit 113 | List res=new ArrayList<>(); 114 | for(int h=0;h<12;h++) 115 | for(int m=0;m<60;m++) 116 | if(Integer.bitCount(h*64+m)==num)//h+m*16 117 | res.add(String.format("%d:%02d",h,m)); 118 | return res; 119 | } 120 | ``` 121 | 122 | **Solution2:Backtracking** 123 | 124 | OPTION: 125 | choose the next charactor in the mapping of next digit. 126 | 127 | RESTRAINT: 128 | if all charactors in the mapping charactors of certain digits are used up , then you have to stop this level of recursion and back to previous level. 129 | 130 | TERMINATION: 131 | if all digits have been considered, then you get the final result. 132 | 133 | ```java 134 | public List readBinaryWatch(int num) { 135 | List res=new ArrayList(); 136 | int[] bits1={1,2,4,8},bits2={1,2,4,8,16,32}; 137 | for(int i=0;i<=num;i++){ 138 | List hours=helper(bits1,i); 139 | List mins=helper(bits2,num-i); 140 | for(Integer h:hours){ 141 | if(h>=12) continue; 142 | for(Integer m:mins){ 143 | if(m>=60) continue; 144 | res.add(h+":"+(m<10?"0"+m:m)); 145 | } 146 | } 147 | } 148 | return res; 149 | } 150 | private List helper(int[] bits,int n){ 151 | List res1=new ArrayList<>(); 152 | backtracking(res1,bits,n,0,0); 153 | return res1; 154 | } 155 | private void backtracking(List res1,int[] bits,int n,int start,int sum){ 156 | if(n==0){ 157 | res1.add(sum); 158 | return; 159 | } 160 | for(int i=start;iinvalid char 182 | boolean exist=backtracking(board,word,i+1,j,idx+1)||backtracking(board,word,i,j+1,idx+1)||backtracking(board,word,i-1,j,idx+1)||backtracking(board,word,i,j-1,idx+1); 183 | board[i][j]^=256;//bit mask->valid char 184 | return exist; 185 | } 186 | ``` 187 | -------------------------------------------------------------------------------- /Classic Backtrackings.md: -------------------------------------------------------------------------------- 1 | # Classic Backtrackings 2 | 3 | Here I list all classic `Backtracking` problems with almost identical solution form. Try your best to understand the codes. 4 | 5 | ## [Palindrome Partitioning](https://leetcode.com/problems/palindrome-partitioning/) 6 | 7 | I think this is also a classic problem. This only difference is to deal with palindrome. 8 | 9 | >Please refer to the `recursion tree` in [this post](https://discuss.leetcode.com/topic/6186/java-backtracking-solution) in Leetcode discussion since this might help you understand most backtracking problems. 10 | 11 | OPTION: 12 | add a substring to 'palindrome list' 13 | 14 | RESTRAINT: 15 | the substring must be a palindrome.=>You have to check it. 16 | 17 | TERMINATION: 18 | as long as you have gone through the whole input string, you finished an iteration, return and go on the next one. 19 | 20 | ```java 21 | public List> partition(String s) { 22 | List> res=new ArrayList>(); 23 | backtracking(res,new ArrayList(),s,0); 24 | return res; 25 | } 26 | private void backtracking(List> res, List list, String s, int start){ 27 | if(start==s.length()){ 28 | res.add(new ArrayList(list)); 29 | return; 30 | } 31 | for(int i=start;i> combine(int n, int k) { 50 | List> res=new ArrayList>(); 51 | backtracking(res,new ArrayList<>(),1,n,k); 52 | return res; 53 | } 54 | private void backtracking(List> res,List comb,int start,int n,int k){ 55 | if(comb.size()==k){ 56 | res.add(new ArrayList<>(comb)); 57 | return; 58 | } 59 | for(int i=start;i<=n;i++){ 60 | comb.add(i); 61 | backtracking(res,comb,i+1,n,k); 62 | comb.remove(comb.size()-1); 63 | } 64 | } 65 | ``` 66 | 67 | ## [Combination Sum](https://leetcode.com/problems/combination-sum/) 68 | 69 | ```java 70 | public List> combinationSum(int[] candidates, int target) { 71 | List> res=new ArrayList>(); 72 | backtracking(candidates,res,new ArrayList(),target,0); 73 | return res; 74 | } 75 | private void backtracking(int[] candidates,List> res,List tmp,int sum,int start){ 76 | if(sum==0) res.add(new ArrayList(tmp)); 77 | for(int i=start;i> combinationSum2(int[] candidates, int target) { 90 | Arrays.sort(candidates); 91 | List> res=new ArrayList>(); 92 | backtracking(candidates,res,new ArrayList(),target,0); 93 | return res; 94 | } 95 | private void backtracking(int[] candidates,List> res,List tmp,int sum,int start){ 96 | if(sum==0) res.add(new ArrayList(tmp)); 97 | for(int i=start;istart&&candidates[i]==candidates[i-1]) continue; 99 | if(candidates[i]<=sum){ 100 | tmp.add(candidates[i]); 101 | backtracking(candidates,res,tmp,sum-candidates[i],i+1); 102 | tmp.remove(tmp.size()-1); 103 | } 104 | } 105 | } 106 | ``` 107 | 108 | ## [Combination Sum III](https://leetcode.com/problems/combination-sum-iii/) 109 | 110 | ```java 111 | public List> combinationSum3(int k, int n) { 112 | List> res = new ArrayList>(); 113 | backtracking(res, new ArrayList(),n, k, 1); 114 | return res; 115 | } 116 | private void backtracking(List> res,List tmp,int n,int k,int start){ 117 | if(n==0&&tmp.size()==k){ 118 | res.add(new ArrayList(tmp));//no return 119 | return; 120 | } 121 | for(int i=start;i<=9;i++){ 122 | tmp.add(i); 123 | backtracking(res,tmp,n-i,k,i+1);//why not i+1?? 124 | tmp.remove(tmp.size()-1); 125 | } 126 | } 127 | ``` 128 | 129 | ## [Permutation](https://leetcode.com/problems/permutations/) 130 | 131 | In this problem, we output all permutations of the array. We don't need to store the `start` value in each recursion since we start at position 0 every time and add only if there is no such element in `tmp` list. 132 | 133 | ```java 134 | public List> permute(int[] nums) { 135 | List> res=new ArrayList>(); 136 | backtracking(res,new ArrayList(),nums); 137 | return res; 138 | } 139 | private void backtracking(List> res,List tmp,int[] nums){ 140 | if(tmp.size()==nums.length){ 141 | res.add(new ArrayList<>(tmp)); 142 | return; 143 | } 144 | for(int i=0;i> permuteUnique(int[] nums) { 163 | List> res=new ArrayList>(); 164 | Arrays.sort(nums); 165 | boolean[] added=new boolean[nums.length]; 166 | backtracking(res,new ArrayList(),nums,used); 167 | return res; 168 | } 169 | private void backtracking(List> res,List tmp,int[] nums,boolean[] added){ 170 | if(tmp.size()==nums.length){ 171 | res.add(new ArrayList<>(tmp)); 172 | return; 173 | } 174 | for(int i=0;i0&&nums[i]==nums[i-1]&&!added[i-1]) continue; 176 | tmp.add(nums[i]); 177 | added[i]=true; 178 | backtracking(res,tmp,nums,added); 179 | tmp.remove(tmp.size()-1); 180 | added[i]=false; 181 | } 182 | } 183 | ``` 184 | 185 | ## [Subsets](https://leetcode.com/problems/subsets/) 186 | 187 | **Solution1: Bit Manipulation** 188 | 189 | > This solution directly captures the intrinsic connection between power set and binary numbers. 190 | When forming a subset, for each element, only 2 possiblities, either it is in the subset or not in the subset, hence we have total number of possible subsets = 2^n.Thinking each element as a bit, it's either on or off when forming the ith subset, and that's the solution! 191 | 192 | ```java 193 | public List> subsets(int[] nums) { 194 | //bit manipulation 195 | List> res=new ArrayList>(); 196 | int setsNum=1< subset=new ArrayList<>(); 199 | for(int j=0;j> subsets(int[] nums) { 214 | List> res=new ArrayList>(); 215 | backtracking(nums,res,new ArrayList(),0); 216 | return res; 217 | } 218 | //[] [1] [1,2] [1,2,3] [1,3] [2] [2,3] [3] 219 | private void backtracking(int[] nums,List> res,List subset,int start){ 220 | res.add(new ArrayList(subset)); 221 | for(int i=start;i> subsetsWithDup(int[] nums) { 233 | List> res=new ArrayList>(); 234 | Arrays.sort(nums); 235 | backtracking(nums,res,new ArrayList(),0); 236 | return res; 237 | } 238 | 239 | private void backtracking(int[] nums,List> res,List subset,int start){ 240 | res.add(new ArrayList(subset)); 241 | for(int i=start;istart&&nums[i]==nums[i-1]) continue; 243 | subset.add(nums[i]); 244 | backtracking(nums,res,subset,i+1); 245 | subset.remove(subset.size()-1); 246 | } 247 | } 248 | ``` 249 | 250 | -------------------------------------------------------------------------------- /k-Sum.md: -------------------------------------------------------------------------------- 1 | # 2Sum, 3Sum, 4Sum 2 | 3 | ## [2 Sum](http://oj.leetcode.com/problems/two-sum/) 4 | 5 | This is a quite classical problem, the `brute-force ` approach runs in `O(n^2)` time to compare pairs with target one by one. 6 | 7 | However, we can optimize this problem by the following two solutions. 8 | 9 | **1.HashMap** 10 | 11 | The first one is using a `HashMap` to memorize the elements appeared and check if the new element can pair with a previous one in the map and add up to 'target'. This algorithm will run in `O(n)` time and `O(n)` space when accessing the hashmap takes constant time. 12 | 13 | ```java 14 | public int[] twoSum(int[] nums, int target) { 15 | HashMap map=new HashMap<>(); 16 | for(int i=0;itarget) r--; 35 | else l++; 36 | return new int[]{0,0}; 37 | } 38 | ``` 39 | *NOTE: Here we output the two numbers int the target pair instead of the two indices.* 40 | 41 | Since we have to sort the array, in order to output the correct indices we should construct a new data structure and store the number and its original index into it. And then we sort this data structure. So from this perspective, this optimization is not as good as the first one. It takes O(nlogn+n)=`O(nlogn)` time and the space complexity depends on the sorting algorithm. 42 | 43 | *In [Two Sum II - Input array is sorted](https://leetcode.com/problems/two-sum-ii-input-array-is-sorted/), we can use this solution and output the indices with only `O(n)` time because the array is sorted.* 44 | 45 | >The problem suggest that there is exactly one solution. However the interviewers might ask you to output all possible solutions. In this case we have to consider removing duplicate pairs. [see @3 Sum] 46 | 47 | 48 | ## [3 Sum](https://leetcode.com/problems/3sum/) 49 | 50 | This is an extension of `2Sum` and the `brute force` solution takes `O(n^3)` time. 51 | 52 | In this problem, there may contain duplicates in the input set, so the `hashmap` solution might not work. It could be easier to skip duplicate triplets when the array is sorted. Thus we should consider sorting the array and use `two pointers`. 53 | 54 | ```java 55 | public List> threeSum(int[] nums) { 56 | List> res=new ArrayList>(); 57 | Arrays.sort(nums);//makes it easier to skip duplicates 58 | for(int i=0;i0&&nums[i]!=nums[i-1])){//avoid duplicate pairs in result. 60 | int l=i+1,h=nums.length-1,sum=0-nums[i]; 61 | while(l target 119 | - the inner loop break immediately when nums[j]*4 < target. 120 | 121 | These two lines save quite some time due to the set up of the test cases in OJ. 122 | 123 | ```java 124 | public List> fourSum(int[] nums, int target) { 125 | List> list = new ArrayList>(); 126 | Arrays.sort(nums); 127 | int second = 0, third = 0, nexti = 0, nextj = 0; 128 | for(int i=0, L=nums.length; i target) return list; // return immediately 130 | for(int j=L-1; j>i+2; j--) { 131 | if(nums[j]<<2 < target) break; // break immediately 132 | int rem = target-nums[i]-nums[j]; 133 | int lo = i+1, hi=j-1; 134 | while(lorem) --hi; 137 | else if(sum=lo && nums[hi]==nums[hi+1]) continue; // avoid duplicate results 142 | } 143 | } 144 | while(j>=1 && nums[j]==nums[j-1]) --j; // skip inner loop 145 | } 146 | while(i> twoSum(ArrayList pairs, int target){ 166 | HashSet hashSet = new HashSet(); 167 | int l = 0; 168 | int r = pairs.size()-1; 169 | ArrayList> res = new ArrayList>(); 170 | while(l=rEnd;j--) 186 | { 187 | if(check(pairs.get(i),pairs.get(j))) 188 | { 189 | ArrayList item = new ArrayList(); 190 | item.add(pairs.get(i).nodes[0].value); 191 | item.add(pairs.get(i).nodes[1].value); 192 | item.add(pairs.get(j).nodes[0].value); 193 | item.add(pairs.get(j).nodes[1].value); 194 | //Collections.sort(item); 195 | Tuple tuple = new Tuple(item); 196 | if(!hashSet.contains(tuple)) 197 | { 198 | hashSet.add(tuple); 199 | res.add(tuple.num); 200 | } 201 | } 202 | } 203 | } 204 | l = lEnd+1; 205 | r = rEnd-1; 206 | } 207 | else if(pairs.get(l).getSum()+pairs.get(r).getSum()>target) 208 | { 209 | r--; 210 | } 211 | else{ 212 | l++; 213 | } 214 | } 215 | return res; 216 | } 217 | private boolean check(Pair p1, Pair p2) 218 | { 219 | if(p1.nodes[0].index == p2.nodes[0].index || p1.nodes[0].index == p2.nodes[1].index) return false; 220 | if(p1.nodes[1].index == p2.nodes[0].index || p1.nodes[1].index == p2.nodes[1].index) return false; 221 | return true; 222 | } 223 | ``` 224 | 225 | [This solution](http://blog.csdn.net/linhuanmars/article/details/24826871) is faster and can be extended to all k Sum problems but would be quite complicated. So this is not very suitable to be asked in an interview. Just remembering the detailed thinking method is enough. 226 | 227 | --------------------------------------------------------------------------------