1. 程式人生 > >Leetcode 經典題目題解

Leetcode 經典題目題解

所列均為個人解答 所用語言Java 儘量都用最優解解答 原題出自Leetcode:https://leetcode.com/problemset/algorithms/ 僅供參考 Single Number code:
public int singleNumber(int[] A) {
    int rst = 0;
    for(int a : A)
        rst ^= a;
    return rst;
}

note:
Java提供的位運算子有:左移( << )、右移( >> ) 、無符號右移( >>> ) 、位與( & ) 、位或( | )、位非( ~ )、位異或( ^ ),除了位非( ~ )是一元操作符外,其它的都是二元操作符。 正數左移一位相當於乘2,右移一位相當於除2

5換算成二進位制: 0000 0000 0000 0000 0000 0000 0000 0101
5右移3位後結果為0,0的二進位制為: 0000 0000 0000 0000 0000 0000 0000 0000        // (用0進行補位)
 -5換算成二進位制: 1111 1111 1111 1111 1111 1111 1111 1011
-5右移3位後結果為-1,-1的二進位制為: 1111 1111 1111 1111 1111 1111 1111 1111   // (用1進行補位)
-5無符號右移3位後的結果 536870911 換算成二進位制: 0001 1111 1111 1111 1111 1111 1111 1111   // (用0進行補位)

5轉換成二制是101,不過int型別的數佔用4位元組(32位),所以前面填了一堆0。

現在想知道,-5在計算機中如何表示?
在計算機中,負數以其正值的補碼形式表達。


原碼:一個整數,按照絕對值大小轉換成的二進位制數,稱為原碼。
比如 00000000 00000000 00000000 00000101 是 5的 原碼。


反碼:將二進位制數按位取反,所得的新二進位制數稱為原二進位制數的反碼。
取反操作指:原為1,得0;原為0,得1。(1變0; 0變1)
比如:將00000000 00000000 00000000 00000101每一位取反,得11111111 11111111 11111111 11111010。
稱:11111111 11111111 11111111 11111010 是 00000000 00000000 00000000 00000101 的反碼。
反碼是相互的,所以也可稱:
11111111 11111111 11111111 11111010 和 00000000 00000000 00000000 00000101 互為反碼。


補碼:反碼加1稱為補碼。
也就是說,要得到一個數的補碼,先得到反碼,然後將反碼加上1,所得數稱為補碼。
比如:00000000 00000000 00000000 00000101 的反碼是:11111111 11111111 11111111 11111010。
那麼,補碼為:
11111111 11111111 11111111 11111010 + 1 = 11111111 11111111 11111111 11111011
所以,-5 在計算機中表達為:11111111 11111111 11111111 11111011。轉換為十六進位制:0xFFFFFFFB。

Maximum Depth of Binary Tree
hint: 遞迴 code:
public int maxDepth(TreeNode root) {
    if(root == null)
        return 0;
    return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
}

Same Tree hint:  遞迴 code:
public boolean isSameTree(TreeNode p, TreeNode q) {
    if(p == null && q == null)
        return true;
    if(p == null || q == null)
        return false;
    if(p.val != q.val )
        return false;
    return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
}


Reverse Integer hint: StringBuilder  或  整數位數操作 code:
public int reverse(int x) {
        int rst = 0;
        while(x != 0){
            if(Math.abs(rst) > 214748364)  // 處理溢位 !! 214748364 9    這個本身反過來也是溢位的 也就是說最後一位只能是1
                return 0;
            rst = rst*10 + x%10;
            x /= 10;
        }
        return rst;
    }

public int reverse(int x) {
        int y = Math.abs(x);
        StringBuilder sb = new StringBuilder(y+"");
        sb.reverse();
        try{
            y = Integer.parseInt(sb.toString());
        }catch(NumberFormatException ex){
            return 0;
        }
       
        return x < 0 ? -y : y;
    }


Best Time to Buy and Sell Stock II hint: 觀察,求序列遞增的增量 code:
public int maxProfit(int[] prices) {
    int sum = 0;
    if(prices.length <= 1)
        return sum;
    for(int i=1; i<prices.length; ++i){
        if(prices[i] > prices[i-1])
            sum += prices[i] - prices[i-1];
    }
    return sum;
}

Linked List Cycle hint: 雙指標 一個走兩步 一個走一步, 如果快指標能追上慢指標 則存在cycle correctness: 分case證明, 走兩步的指標一定能與走一步的指標在某處相遇 且不超過一輪 或者可以思考 每一步快指標會追上一步,距離是逐一遞減,因此兩者距離必定經過0 即相遇點 如果快指標一次走三步,四步, 情況會怎樣? code:
public boolean hasCycle(ListNode head) {
    ListNode fast = head;
    ListNode slow = head;
    
    while(fast != null && fast.next != null){
        fast = fast.next.next;
        slow = slow.next;
        if(fast == slow)
            return true;
    }
    return false;       
}

Binary Tree Preorder Traversal hint: use stack for the non-recursion solution code:
public List<Integer> preorderTraversal(TreeNode root) {
    List<Integer> rst = new ArrayList<Integer>();
    if(root == null)
        return rst;
    Stack<TreeNode> stack = new Stack<TreeNode>();
    stack.push(root);
    while(!stack.isEmpty()){
        root = stack.pop();
        rst.add(root.val);
        if(root.right != null)
            stack.push(root.right);
        if(root.left != null)
            stack.push(root.left);
    }
    return rst;
}

Binary Tree Inorder Traversal hint: 難點在於如何處理輸出順序:對於每一個棧頂的節點 先將其和其所有left-most節點壓入棧  直到棧頂節點left child為空, 輸出該節點val。 再壓入其右節點 進行下一輪迴圈, 注意此時指標目標
public List<Integer> inorderTraversal(TreeNode root) {
    List<Integer> rst = new ArrayList<Integer>();
    if(root == null)
        return rst;
    Stack<TreeNode> stack = new Stack<TreeNode>();
    TreeNode curr = root;
    while(!stack.isEmpty() || curr != null){
        while(curr != null){
            stack.push(curr);
            curr = curr.left;
        }
        curr = stack.pop();
        rst.add(curr.val);
        curr = curr.right;
    }
    return rst;
}

Populating Next Right Pointers in Each Node hint: 觀察結構  遞迴解決
public void connect(TreeLinkNode root) {
    if(root == null || root.left == null || root.right == null)
        return;
    root.left.next = root.right;
    if(root.next != null)
        root.right.next = root.next.left;
    connect(root.right);
    connect(root.left);
}

Remove Duplicates from Sorted List hint: list操作
public ListNode deleteDuplicates(ListNode head) {
        if(head == null)
            return head;
        ListNode curr = head;
        while(curr.next != null){
            if(curr.val == curr.next.val)
                curr.next = curr.next.next;
            else
                curr = curr.next;
        }
        return head;
    }

Search Insert Position hint: linear array search 秒殺
public int searchInsert(int[] A, int target) {
    for(int i=0; i<A.length; ++i){
        if(A[i] == target || A[i] > target)
            return i;
    }
    return A.length;
}
binary search:
public int searchInsert(int[] nums, int target) {
        int left = 0;
        int right = nums.length-1;
        int rst = 0;
       
        while(left <= right){
            if(left == right){
                rst = target <= nums[left] ? left : left+1;
                break;
            }
            int mid = left + (right-left)/2;
            if(nums[mid] == target){
                rst = mid;
                break;
            }
            else if(nums[mid] > target){
                right = mid;
            }
            else
                left = mid+1;
        }
       
        return rst;
    }

Climbing Stairs hint: 一維DP 
public int climbStairs(int n) {
        int[] dp = new int[n+1];
        dp[0] = 1;
        dp[1] = 1;

        for(int i=2; i<=n; ++i){
            dp[i] = dp[i-1] + dp[i-2];
        }

        return dp[n];
}

Maximum Subarray hint:  O(n) 陣列線性掃描
public int maxSubArray(int[] A) {
    int max = Integer.MIN_VALUE;
    int sum = 0;
    for(int i=0; i<A.length; i++){
        sum += A[i];
        if(sum > max)
            max = sum;
        if(sum < 0)
            sum = 0;
    }
    return max;
}

dp:
public int maxSubArray(int[] A) {
        int[] dp = new int[A.length];
        dp[0] = A[0];
        for(int i=1; i<A.length; ++i){
            if(dp[i-1] < 0)
                dp[i] = A[i];
            else
                dp[i] = A[i] + dp[i-1];
        }
        int max = Integer.MIN_VALUE;
        for(int i=0; i<dp.length; ++i)
            if(dp[i] > max)
                max = dp[i];
        return max;
    }

Roman to Integer
public int romanToInt(String s) {
    int rst = 0;
 
    for(int i=0; i<s.length(); i++){
        if(i>0 && charToNum(s.charAt(i)) > charToNum(s.charAt(i-1)))
            rst += (charToNum(s.charAt(i)) - 2*charToNum(s.charAt(i-1))); 
        else 
            rst += charToNum(s.charAt(i));
    }
    return rst;
} 
 
private int charToNum(char c){ 
    switch(c){
    case 'I': return 1;
    case 'V': return 5;
    case 'X': return 10;
    case 'L': return 50;
    case 'C': return 100;
    case 'D': return 500;
    case 'M': return 1000;
    default: return 0;
    }
}
N-Queens II hint: cols[i] 記錄第i行的queen放在了第幾列。
public int totalNQueens(int n) {
    int[] cols = new int[n];
    return dfs(cols, n, 0);
}

public int dfs(int[] cols, int n, int row){
    if(row == n){
        return 1;
    }
    
    int num = 0;
    for(int i=0; i<n; ++i){
        boolean used = false;
        for(int j=0; j<row; ++j)
            if(cols[j] == i || cols[j] + j == i + row || cols[j] - j == i - row){
                used = true;
                break;
            }
        if(!used){
            cols[row] = i; 
            num += dfs(cols, n, row+1);
        }
    }
    
    return num;
}

public int totalNQueens(int n) {
        int[] used = new int[n];
        int[] ang = new int[2*n];
        int[] anti = new int[2*n];
       
        return dfs(used, ang, anti, n, 0);
    }
   
    private int dfs(int[] used, int[] ang, int[] anti, int n, int k){
        if(k == n)
            return 1;
           
        int count = 0;
        for(int i=0; i<n; ++i){
            if(used[i] == 0 && ang[i+k] == 0 && anti[i-k+n] == 0){
                used[i] = 1;
                ang[i+k] = 1;
                anti[i-k+n] = 1;
                count += dfs(used, ang, anti, n, k+1);
                used[i] = 0;
                ang[i+k] = 0;
                anti[i-k+n] = 0;
            }
        }
       
        return count;
    }

Single Number II hint: 因為題目已經說了,除了一個數字以外,其他的都出現了3次,如果我們把那個特殊的數剔除,並把剩下的數於每一位來加和的話,每一位上1出現的次數必然都是3的倍數。所以,解法就在這裡,將每一位數字分解到32個bit上,統計每一個bit上1出現的次數。最後對於每一個bit上1出現的個數對3取模,剩下的就是結果。
public int singleNumber(int[] A) {
        int[] bits = new int[32];
        int rst = 0;
        for(int i=31; i>=0; --i){
            for(int j=0; j<A.length; j++)
                bits[i] += (A[j]>>i)&1;
            bits[i] %= 3;
            rst = (rst<<1)+bits[i];
        }
        return rst;
    }

Integer to Roman
public String intToRoman(int num) {
    String[] roman = {"I", "V", "X", "L", "C", "D", "M"};
    String rst = ""; 

    int level = 1000; 
    for(int i=6; i>=0; i-=2){
        int digit = num/level;
            if(digit != 0){ 
                if(digit <= 3){
                    for(int j=0; j<digit; ++j)
                        rst += roman[i];
                }
            else if(digit == 4){
                rst += roman[i];
                rst += roman[i+1];
            }
            else if(digit == 5)
                rst += roman[i+1];
            else if(digit <= 8){
                rst += roman[i+1];
                for(int j=0; j<digit-5; ++j)
                    rst += roman[i];
            }
            else if(digit == 9){
                rst += roman[i];
                rst += roman[i+2];
            }
        }
        num %= level;
        level /= 10;
    }
       
    return rst;
}

Merge Two Sorted Lists
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
    ListNode rst = new ListNode(0);
    ListNode curr = rst;
    while(l1 != null && l2 != null){
        if(l1.val < l2.val){
            curr.next= l1;
            curr = curr.next;
            l1 = l1.next;
        }
        else{
            curr.next = l2;
            curr = curr.next;
            l2 = l2.next;
        }
    }
    while(l1 != null){
        curr.next = l1;
        curr = curr.next;
        l1 = l1.next;
    }
    while(l2 != null){
        curr.next = l2;
        curr = curr.next;
        l2 = l2.next;
    }

    return rst.next;
}

遞迴解法
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        if(l1 == null && l2 == null)
         return null;
        else if(l1 == null || l2 == null)
         return (l1!=null ? l1 : l2);
         
        ListNode head;
        if(l1.val < l2.val){
         head = l1;
         head.next = mergeTwoLists(l1.next, l2);
        }
        else{
         head = l2;
         head.next = mergeTwoLists(l1, l2.next);
        }
       
        return head;
    }

Remove Element hint: 雙指標操作
public int removeElement(int[] nums, int val) {
        if(nums == null || nums.length == 0)
            return 0;
        int p = 0;
        for(int i=0; i<nums.length; ++i){
            if(nums[i] != val){
                nums[p++] = nums[i];
            }
        }
        return p;
    }

Convert Sorted Array to Binary Search Tree hint: 遞迴
public TreeNode sortedArrayToBST(int[] num) {
        if(num.length < 1)
            return null;
        return bst(num, 0, num.length-1);
    }
   
    public TreeNode bst(int[] num, int start, int end){
        if(start > end)
            return null;
        int mid = start + (end-start)/2;                          // 防止溢位
        TreeNode node = new TreeNode(num[mid]);
        node.left = bst(num, start, mid-1);
        node.right = bst(num, mid+1, end);
        return node;
    }

Balanced Binary Tree hint: 設個外部變數, 通過計算高度遍歷tree
public boolean isBalanced(TreeNode root) {
        return height(root) != -1;
    }
   
    public int height(TreeNode node){
        if(node == null)
            return 0;
        int lefth = height(node.left);
        int righth = height(node.right);
        if(lefth < 0 || righth < 0 || Math.abs(lefth-righth) > 1)
            return -1;
        return Math.max(lefth, righth) + 1;
    }

Remove Duplicates from Sorted Array hint: 雙指標掃陣列
public int removeDuplicates(int[] A) {
    if(A.length <= 1)
        return A.length;
    int index = 0;
    for(int i=1; i<A.length; ++i){
        if(A[i] == A[index])
            continue;
        A[++index] = A[i];
    }
    return index+1;
}

Swap Nodes in Pairs
public ListNode swapPairs(ListNode head) {
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode prev = dummy;
        ListNode curr = head;
        while(curr != null && curr.next != null){
            prev.next = curr.next;
            curr.next = curr.next.next;
            prev.next.next = curr;
            prev = curr;
            curr = curr.next;
        }
        return dummy.next;
    }


Symmetric Tree note: 兩種解法 iterative method:
public boolean isSymmetric(TreeNode root) {
    if(root == null)
        return true;
    Queue<TreeNode> qleft = new LinkedList<TreeNode>();
    Queue<TreeNode> qright = new LinkedList<TreeNode>();

    qleft.offer(root.left);
    qright.offer(root.right);
    while(!qleft.isEmpty() && !qright.isEmpty()){
        TreeNode left = qleft.poll();
        TreeNode right = qright.poll();
        if(left == null && right == null)
            continue;
        if(left == null || right == null || right.val != left.val)
            return false;
        qleft.offer(left.left);
        qright.offer(right.right);
        qleft.offer(left.right);
        qright.offer(right.left);
    }
    return true;
}
recursion method:
public boolean isSymmetric(TreeNode root) {
    if(root == null)
        return true;
    return isMirror(root.left, root.right);
}

private boolean isMirror(TreeNode left, TreeNode right){
    if(left == null && right == null)
        return true;
    if(left == null || right == null || left.val != right.val)
        return false;
    return isMirror(left.right, right.left) && isMirror(left.left, right.right);
}

Sort Colors hint: 陣列三指標操作
public void sortColors(int[] A) {
    int left = 0;
    int curr = 0;
    int right = A.length - 1;
    while(curr <= right){
        if(A[curr] == 0){
            A[curr] = A[left];
            A[left++] = 0;
        }
        else if(A[curr] == 2){
            A[curr] = A[right];
            A[right--] = 2;
        }
        else{
            ++curr;
        }
        
       if(curr < left)
            curr++;
    }
}


Merge Sorted Array hint: 從後往前 從大到小填空
public void merge(int A[], int m, int B[], int n) {
    int inda = m - 1;
    int indb = n - 1;
    for(int i=m+n-1; i>=0; --i){
        if(inda < 0)
            A[i] = B[indb--];
        else if(indb < 0)
            A[i] = A[inda--];
        else if(A[inda] > B[indb])
            A[i] = A[inda--];
        else
            A[i] = B[indb--];
    }
}

Gray Code recursive: 
public List<Integer> grayCode(int n) {
    List<Integer> rst = new ArrayList<Integer>();
    if(n == 0){
        rst.add(0);
        return rst;
    }
    
    List<Integer> list = grayCode(n-1);
    for(int i=0; i<list.size(); ++i){
        rst.add((list.get(i)<<1) + i%2);
        rst.add((list.get(i)<<1) + (i+1)%2);
    }

    return rst;
}

Iterative: n=k時的Gray Code,相當於n=k-1時的Gray Code的逆序 加上 1<<k
public List<Integer> grayCode(int n) {
        List<Integer> rst = new ArrayList<Integer>();
        rst.add(0);
       
        for(int i=0; i<n; ++i)
            for(int j=rst.size()-1; j>=0; --j){
                rst.add(rst.get(j) + (1<<i));
            }
        return rst;
    }

Plus One
public int[] plusOne(int[] digits) {
    int add = 1;
    for(int i=digits.length-1; i>=0; --i){
        int sum = digits[i] + add;
        digits[i] = sum%10;
        add = sum/10;
    }
    
    int[] rst = digits;
    if(add == 1){
        rst = new int[digits.length+1];
        rst[0] = 1;
        for(int i=1; i<rst.length; ++i)
            rst[i] = digits[i-1];
    }
    return rst;    
}

Unique Paths hint: DP 二維:
public int uniquePaths(int m, int n) {
    int[][] dp = new int[m][n];
    for(int i=0; i<m; ++i)
        dp[i][0] = 1;
    for(int i=0; i<n; ++i)
        dp[0][i] = 1;
    for(int i=1; i<m; ++i)
        for(int j=1; j<n; ++j){
            dp[i][j] = dp[i-1][j] + dp[i][j-1];
        }
    return dp[m-1][n-1];
}

一維:
public int uniquePaths(int m, int n) {
    int[] dp = new int[m];
    dp[0] = 1;
    for(int i=0; i<n; ++i)
        for(int j=1; j<m; ++j){
            dp[j] = dp[j] + dp[j-1];
        }
    return dp[m-1];
}
Unique Binary Search Trees
public int numTrees(int n) {
        if(n <= 1)
            return 1;
        int rst = 0;
        for(int i=0; i<n; ++i){
            rst += numTrees(i) * numTrees(n-i-1);
        }
        return rst;
    }

dp
public int numTrees(int n) {
        if(n <= 1)
            return n;
        int[] dp = new int[n+1];
        dp[0] = 1;
        dp[1] = 1;
        for(int i=2; i<=n; ++i){
            for(int j=0; j<i; j++)
                dp[i] += dp[j]*dp[i-j-1];
        }
        return dp[n];
    }

Find Minimum in Rotated Sorted Array
public int findMin(int[] num) {
        return getMin(num, 0, num.length-1);
    }
   
    public int getMin(int[] num, int left, int right){
        if(left == right || num[left] < num[right])
            return num[left];
        int mid = left + (right-left)/2;
        if(num[right] < num[mid])
            return getMin(num, mid+1, right);
        else
            return getMin(num, left, mid);
    }

Find Minimum in Rotated Sorted Array II
public int findMin(int[] nums) {
        if(nums == null || nums.length == 0)
            return -1;
        return findMin(nums, 0, nums.length-1);
    }
   
    private int findMin(int[] nums, int left, int right){
        if(left == right || nums[left] < nums[right])
            return nums[left];
       
        int mid = left + (right - left)/2;
        if(nums[mid] < nums[right]){
            return findMin(nums, left, mid);
        }
        else if(nums[mid] > nums[right]){
            return findMin(nums, mid+1, right);
        }
        else
            return findMin(nums, left, right-1);
    }

Iterative solution:
public int findMin(int[] nums) {
        int left = 0;
        int right = nums.length-1;
       
        while(left <= right){
            if(left == right || nums[left] < nums[right])
                return nums[left];
            if(nums[left] == nums[right]){
                right--;
                continue;
            }
            int mid = left + (right-left)/2;
            if(nums[mid] > nums[right])
                left = mid + 1;
            else
                right = mid;
        }
       
        return nums[left];
    }

Find Peak Element Given an input array wherenum[i] ≠ num[i+1]find a peak element and return its index.
public int findPeakElement(int[] nums) {
        if(nums == null || nums.length <= 1)
            return 0;
        int left = 0;
        int right = nums.length-1;
        while(left + 1 < right){
            int mid = left + (right-left)/2;
            if(nums[mid] > nums[mid-1] && nums[mid] > nums[mid+1])
                return mid;
            if(nums[mid] < nums[mid-1])
                right = mid;
            else
                left = mid;
        }
       
        return nums[left] > nums[right] ? left : right;
    }

Container With Most Water
public int maxArea(int[] height) {
        if(height.length <= 1)
            return 0;
        int left = 0;
        int right = height.length-1;
        int max = 0;
        while(left < right){
            int val = Math.min(height[left], height[right]) * (right - left);
            if(val > max)
                max = val;
            if(height[left] < height[right])
                left++;
            else
                right--;
        }
        return max;
    }


Rotate Image
public void rotate(int[][] matrix) {
        int row = matrix.length;
        int col = matrix[0].length;
       
        for(int i=0; i<row-1; ++i)
            for(int j=i; j<col; ++j){
                int temp = matrix[i][j];
                matrix[i][j] = matrix[j][i];
                matrix[j][i] = temp;
            }
        for(int i=0; i<row; ++i)
            for(int j=0; j<col/2; ++j){
                int temp = matrix[i][j];
                matrix[i][j] = matrix[i][col-1-j];
                matrix[i][col-1-j] = temp;
            }
    }

Generate Parentheses
public List<String> generateParenthesis(int n) {
        List<String> rst = new ArrayList<String>();
        dfs(rst, n, n, "");
        return rst;
    }
   
    public void dfs(List<String> list, int l, int r, String str){
        if(l == 0){
            while(r-- > 0)
                str += ")";
            list.add(str);
            return;
        }
        dfs(list, l-1, r, str+"(");
        if(l < r)
            dfs(list, l, r-1, str+")");
    }

Permutations
public List<List<Integer>> permute(int[] num) {
        List<List<Integer>> rst = new ArrayList<List<Integer>>();
        dfs(rst, num, new ArrayList<Integer>());
        return rst;
    }
   
    public void dfs(List<List<Integer>> rst, int[] num, List<Integer> list){
        if(list.size() == num.length){
            rst.add(new ArrayList<Integer>(list));
            return;
        }
        for(int i=0; i<num.length; ++i)
            if(!list.contains(num[i])){
                list.add(num[i]);
                dfs(rst, num, list);
                list.remove(list.size()-1);
            }
       
    }

Minimum Path Sum
public int minPathSum(int[][] grid) {
        int n = grid[0].length;
        int[] dp = new int[n];
       
        dp[0] = grid[0][0];
        for(int i=1; i<n; ++i)
            dp[i] = grid[0][i] + dp[i-1];
       
        for(int i=1; i<grid.length; ++i){
            dp[0] += grid[i][0];
            for(int j=1; j<n; ++j)
                dp[j] = Math.min(dp[j], dp[j-1]) + grid[i][j];
        }
       
        return dp[n-1];
    }

Search a 2D Matrix
public boolean searchMatrix(int[][] matrix, int target) {
        if(matrix == null || matrix.length == 0 || matrix[0].length == 0)
            return false;
        int m = matrix.length;
        int n = matrix[0].length;
        int left = 0;
        int right = m*n-1;
        while(left <= right){
            int mid = left + (right-left)/2;
            if(matrix[mid/n][mid%n] == target)
                return true;
            else if(matrix[mid/n][mid%n] < target)
                left = mid+1;
            else
                right = mid-1;
        }
        return false;
    }

Path Sum
public boolean hasPathSum(TreeNode root, int sum) {
        if(root == null)
            return false;
           
        if(root.left == null && root.right == null)
            return sum == root.val;
       
        return hasPathSum(root.left, sum-root.val) || hasPathSum(root.right, sum-root.val);
    }
Combinations
public List<List<Integer>> combine(int n, int k) {
        List<List<Integer>> rst = new ArrayList<List<Integer>>();
        if(n == 0 || n < k)
            return rst;
        dfs(rst, new ArrayList<Integer>(), n, 1, k);
        return rst;
    }
   
    private void dfs(List<List<Integer>> rst, List<Integer> list, int n, int p, int k){
        if(k == 0){
            rst.add(new ArrayList<Integer>(list));
            return;
        }
       
        for(int i=p; i<=n; ++i){
            list.add(i);
            dfs(rst, list, n, i+1, k-1);
            list.remove(list.size()-1);
        }
    }

Binary Tree Postorder Traversal
public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> rst = new ArrayList<Integer>();
        Stack<TreeNode> stack = new Stack<TreeNode>();
       
        stack.push(root);
        while(!stack.isEmpty()){
            TreeNode nd = stack.pop();
            if(nd == null)
                continue;
            rst.add(0, nd.val);
            stack.push(nd.left);
            stack.push(nd.right);
        }
        return rst;
    }

Search in Rotated Sorted Array
public int search(int[] A, int target) {
        return binarySearch(A, target, 0, A.length-1);
    }
   
    public int binarySearch(int[] A, int target, int left, int right){
        if(left > right)
            return -1;
        int mid = left + (right-left)/2;
        if(A[mid] == target)
            return mid;
        if(A[left] < A[right]){
            if(A[mid] > target)
                return binarySearch(A, target, left, mid);
            else
                return binarySearch(A, target, mid+1, right);
        }
        else if(A[mid] < A[right]){
            if(target > A[mid] && target <= A[right])
                return binarySearch(A, target, mid+1, right);
            else
                return binarySearch(A, target, left, mid);
        }
        else{
            if(target >= A[left] && target < A[mid])
                return binarySearch(A, target, left, mid);
            else
                return binarySearch(A, target, mid+1, right);
        }
    }

Search in Rotated Sorted Array II
public boolean search(int[] A, int target) {
        int left = 0;
        int right = A.length - 1;
        while(left <= right){
            int mid = left + (right-left)/2;
            if(A[mid] == target)
                return true;
            if(A[left] < A[right]){
                if(A[mid] > target)
                    right = mid;
                else
                    left = mid+1;
            }
            else if(A[mid] == A[left] && A[mid] == A[right])
                left++;
            else{
                if(A[mid] >= A[left]){
                    if(A[mid] > target && A[left] <= target)
                        right = mid;
                    else
                        left = mid+1;
                }
                else{
                    if(A[mid] < target && A[right] >= target)
                        left = mid+1;
                    else
                        right = mid;
                }
            }
        }
        return false;
    }

Populating Next Right Pointers in Each Node II
public void connect(TreeLinkNode root) {
        if(root == null || root.left == null && root.right == null)
            return;
        if(root.left != null)
            root.left.next = root.right == null ? getNode(root.next) : root.right;
        if(root.right != null)
            root.right.next = getNode(root.next);
           
        connect(root.right);
        connect(root.left);
    }
   
    public TreeLinkNode getNode(TreeLinkNode node){
        if(node == null)
            return null;
        if(node.left != null)
            return node.left;
        if(node.right != null)
            return node.right;
        return getNode(node.next);
    }

Binary Tree Level Order Traversal II
public List<List<Integer>> levelOrderBottom(TreeNode root) {
        List<List<Integer>> rst = new ArrayList<List<Integer>>();
        if(root == null)
            return rst;
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        List<Integer> list = new ArrayList<Integer>();
        queue.offer(root);
        int count = 0;
        int num = 1;
        while(!queue.isEmpty()){
            TreeNode node = queue.poll();
            num--;
               
            list.add(node.val);
            if(node.left != null){
                queue.offer(node.left);
                count++;
            }
            if(node.right != null){
                queue.offer(node.right);
                count++;
            }
           
            if(num == 0){
                rst.add(0, new ArrayList(list));
                list.clear();
                num = count;
                count = 0;
            }
        }
        return rst;
    }

Set Matrix Zeroes
public void setZeroes(int[][] matrix) {
        int row = matrix.length;
        int col = matrix[0].length;
       
        boolean rowZero = false;
        boolean colZero = false;
       
        for(int i=0; i<col; ++i)
            if(matrix[0][i] == 0)
                rowZero = true;
        for(int i=0; i<row; ++i)
            if(matrix[i][0] == 0)
                colZero = true;
       
        for(int i=1; i<row; ++i)
            for(int j=1; j<col; ++j)
                if(matrix[i][j] == 0){
                    matrix[i][0] = 0;
                    matrix[0][j] = 0;
                }
        for(int i=1; i<row; ++i)
            for(int j=1; j<col; ++j)
                if(matrix[i][0] == 0 || matrix[0][j] == 0)
                    matrix[i][j] = 0;
       
        if(rowZero)
            for(int i=0; i<col; ++i)
                matrix[0][i] = 0;
        if(colZero)
            for(int i=0; i<row; ++i)
                matrix[i][0] = 0;
    }

Remove Duplicates from Sorted Array II
public int removeDuplicates(int[] nums) {
        if(nums == null || nums.length == 0)
            return 0;
        int left = 0;
        int right = 1;
        int count = 0;
        while(right < nums.length){
            if(nums[right] == nums[left]){
                ++count;
                if(count < 2){
                    nums[++left] = nums[right++];
                } else{
                    right++;
                }
            }
            else{
                count = 0;
                nums[++left] = nums[right++];
            }
        }
       
        return left + 1;
    }

public int removeDuplicates(int[] A) {
        if(A.length <= 2)
            return A.length;
        int p = 2;
        for(int i=2; i<A.length; ++i){
            if(A[i] != A[p-2])
                A[p++] = A[i];
        }
        return p;
    }

Subsets bit operation methods 請見解答pdf
public List<List<Integer>> subsets(int[] S) {
        List<List<Integer>> rst = new ArrayList<List<Integer>>();
        Arrays.sort(S);
        dfs(rst, new ArrayList<Integer>(), S, 0);
        return rst;
    }
   
    public void dfs(List<List<Integer>> rst, List<Integer> list, int[] S, int n){
        if(n >= S.length){
            rst.add(new ArrayList<Integer>(list));
            return;
        }
       
        dfs(rst, list, S, n+1);
        list.add(S[n]);
        dfs(rst, list, S, n+1);
        list.remove(list.size()-1);
    }

Binary Tree Level Order Traversal
public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> rst = new ArrayList<List<Integer>>();
        print(rst, root, 1);
        return rst;
    }
   
    public void print(List<List<Integer>> rst, TreeNode node, int level){
        if(node == null)
            return;
        if(rst.size() < level){
            List<Integer> list = new ArrayList<Integer>();
            list.add(node.val);
            rst.add(list);
        }
        else
            rst.get(level-1).add(node.val);
        print(rst, node.left, level+1);
        print(rst, node.right, level+1);
    }

Sum Root to Leaf Numbers
private int sum;
   
    public int sumNumbers(TreeNode root) {
        sum = 0;
        dfs(root, 0);
        return sum;
    }
   
    public void dfs(TreeNode node, int num){
        if(node == null)
            return;
        if(node.left == null && node.right == null){
            sum += num*10 + node.val;
        }
        dfs(node.left, 10*num + node.val);
        dfs(node.right, 10*num + node.val);
    }

Trapping Rain Water two pointers, value copy when traversal
public int trap(int[] A) { 
        int left = 0;
        int right = A.length-1;
        int sum = 0;
       
        while(right-left > 1){
            if(A[left] < A[right]){
                sum += A[left+1]<A[left] ? A[left]-A[left+1] : 0;
                A[left+1] = Math.max(A[left], A[left+1]);
                left++;
            }
            else{
                sum += A[right-1]<A[right] ? A[right]-A[right-1] : 0;
                A[right-1] = Math.max(A[right], A[right-1]);
                right--;
            }
        }
        return sum;
    }

public int trap(int[] height) {
        if(height == null || height.length <= 2)
            return 0;
        int rst = 0;
        int left= 0;
        int right = height.length-1;
        int h = Math.min(height[left], height[right]);
       
        while(left < right){
            if(height[left] < height[right]){
                rst += h > height[left] ? h - height[left] : 0;
                if(height[++left] > h)
                    h = Math.min(height[left], height[right]);
            }
            else{
                rst += h > height[right] ? h - height[right] : 0;
                if(height[--right] > h)
                    h = Math.min(height[left], height[right]);
            }
        }
       
        return rst;
    }