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 where num[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;
    }


Minimum Depth of Binary Tree
public int minDepth(TreeNode root) {
        return minDepth(root, false);
    }
   
    public int minDepth(TreeNode node, boolean hasBrother){
        if(node == null)
            return hasBrother ? Integer.MAX_VALUE : 0;
        return 1 + Math.min(minDepth(node.left, node.right != null), minDepth(node.right, node.left != null));
    }

public int minDepth(TreeNode root) {
        if(root == null)
            return 0;
        if(root.left == null && root.right == null)
            return 1;
        if(root.left != null && root.right != null)
            return 1+Math.min(minDepth(root.left), minDepth(root.right));
        if(root.left != null)
            return 1+minDepth(root.left);
        else
            return 1+minDepth(root.right);
    }


Palindrome Number
public boolean isPalindrome(int x) {
        if(x < 0)
            return false;
        int d = 1;
        int y = x/10;
        while(y > 0){
            y /= 10;
            d *= 10;
        }
        while(d > 1){
            if(x/d != x%10)
                return false;
            x = (x - d*(x/d))/10;
            d /= 100;
        }
        return true;
    }


Remove Nth Node From End of List
two pointers, elegant!!
public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode p = dummy;
        ListNode q = dummy;
        for(int i=0; i<n; ++i)
            q = q.next;
        while(q.next != null){
            q = q.next;
            p = p.next;
        }
        p.next = p.next.next;
        return dummy.next;
    }


Unique Paths II
public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        int row = obstacleGrid.length;
        int col = obstacleGrid[0].length;
       
        int[] dp = new int[col];
        if(obstacleGrid[0][0] == 0)
                dp[0] = 1;
        for(int i=0; i<row; ++i){
            if(obstacleGrid[i][0] == 1)
                dp[0] = 0;
            for(int j=1; j<col; ++j){
                if(obstacleGrid[i][j] == 1)
                    dp[j] = 0;
                else
                    dp[j] += dp[j-1];
            }
        }
        return dp[col-1];
    }


Longest Consecutive Sequence
public int longestConsecutive(int[] num) {
        Map<Integer, Boolean> map = new HashMap<Integer, Boolean>();
        for(int i=0; i<num.length; ++i)
            map.put(num[i], false);
       
        int max = 0;
        for(int x : num){
            if(map.get(x))
                continue;
            map.put(x, true);
            int len = 1;
            for(int i=1; map.containsKey(x+i); ++i){
                len++;
                map.put(x+i, true);
            }
            for(int i=1; map.containsKey(x-i); ++i){
                len++;
                map.put(x-i, true);
            }
            if(len > max)
                max = len;
        }
       
        return max;
    }


Flatten Binary Tree to Linked List
public void flatten(TreeNode root) {
        while(root != null){
            if(root.left != null){
                getRightMost(root.left).right = root.right;
                root.right = root.left;
                root.left = null;
            }
            root = root.right;
        }
    }
   
    public TreeNode getRightMost(TreeNode node){
        while(node.right != null)
            node = node.right;
        return node;
    }


Valid Parentheses
public boolean isValid(String s) {
        Stack<Character> stack = new Stack<Character>();
        for(int i=0; i<s.length(); ++i){
            char ch = s.charAt(i);
            if(ch == '(' || ch == '[' || ch == '{')
                stack.push(ch);
            else if(stack.isEmpty())
                return false;
            else{
                char ch2 = stack.pop();
                if(ch == ')' && ch2 != '(' || ch == '[' && ch2 != ']' || ch == '{' && ch2 != '}')
                    return false;
            }
        }
        return stack.isEmpty();
    }


Search for a Range
two time binary search to find both left bound and right bound
public int[] searchRange(int[] A, int target) {
        int[] rst = new int[2];
        rst[0] = -1;
        rst[1] = -1;
       
        int left = 0;
        int right = A.length-1;
        while(left <= right){
            int mid = left + (right-left)/2;
            if(A[mid] == target){
                rst[0] = mid;
                right = mid-1;
            }
            else if(A[mid] < target)
                left = mid+1;
            else
                right = mid-1;
        }
        left = 0;
        right = A.length-1;
        while(left <= right){
            int mid = left + (right-left)/2;
            if(A[mid] == target){
                rst[1] = mid;
                left = mid+1;
            }
            else if(A[mid] < target)
                left = mid+1;
            else
                right = mid-1;
        }
        return rst;
    }


Valid Sudoku
public boolean isValidSudoku(char[][] board) {
        for(int i=0; i<9; ++i){
            int[] row = new int[10];
            int[] col = new int[10];
            for(int j=0; j<9; ++j){
                if(board[i][j] != '.'){
                    int val = board[i][j] - '0';
                    if(row[val] == 1)
                        return false;
                    else
                        row[val] = 1;
                }
                if(board[j][i] != '.'){
                    int val = board[j][i] - '0';
                    if(col[val] == 1)
                        return false;
                    else
                        col[val] = 1;
                }
            }
        }
       
        for(int i=0; i<9; i+=3)
            for(int j=0; j<9; j+=3){
                int[] cell = new int[10];
                for(int m=0; m<3; ++m)
                    for(int n=0; n<3; ++n){
                        if(board[i+m][j+n] != '.'){
                            int val = board[i+m][j+n] - '0';
                            if(cell[val] == 1)
                                return false;
                            else
                                cell[val] = 1;
                        }
                    }
            }
        return true;
    }



Subsets II
public List<List<Integer>> subsetsWithDup(int[] num) {
        List<List<Integer>> rst = new ArrayList<List<Integer>>();
        Arrays.sort(num);
        dfs(rst, new ArrayList<Integer>(), num, 0);
        return rst;
    }
   
    public void dfs(List<List<Integer>> rst, List<Integer> list, int[] num, int n){
        if(n >= num.length){
            rst.add(new ArrayList<Integer>(list));
            return;
        }
       
        list.add(num[n]);
        dfs(rst, list, num, n+1);
        list.remove(list.size()-1);
        int i = 1;
        for(; i+n<num.length; ++i)
            if(num[n+i] != num[n])
                break;
        dfs(rst, list, num, n+i);
    }


Jump Game
public boolean canJump(int[] A) {
        int term = 0;
        int p = 0;
        while(term < A.length && term >= p){
            if(p + A[p] > term)
                term = p + A[p];
            p++;
        }
        return term >= A.length-1;
    }


Combination Sum
public List<List<Integer>> combinationSum(int[] candidates, int target) {
        List<List<Integer>> rst = new ArrayList<List<Integer>>();
        Arrays.sort(candidates);
        dfs(rst, new ArrayList<Integer>(), candidates, 0, target);
        return rst;
    }
   
    public void dfs(List<List<Integer>> rst, List<Integer> list,int[] cand, int n, int target){
        if(target == 0){
            rst.add(new ArrayList<Integer>(list));
            return;
        }
        if(target < 0 || n >= cand.length || cand[n] > target)
            return;
           
        list.add(cand[n]);
        dfs(rst, list, cand, n, target-cand[n]);
        list.remove(list.size()-1);
        dfs(rst, list, cand, n+1, target);
    }

public List<List<Integer>> combinationSum(int[] candidates, int target) {
        List<List<Integer>> rst = new ArrayList<List<Integer>>();
        Arrays.sort(candidates);
        dfs(rst, new ArrayList<Integer>(), candidates, 0, target);
        return rst;
    }
   
    private void dfs(List<List<Integer>> rst, List<Integer> list, int[] cand, int k, int target){
        if(target == 0){
            rst.add(new ArrayList<Integer>(list));
            return;
        }
       
        for(int i=k; i<cand.length; ++i){
            if(cand[i] <= target){
                list.add(cand[i]);
                dfs(rst, list, cand, i, target-cand[i]);
                list.remove(list.size()-1);
            }
        }
    }


Partition List
public ListNode partition(ListNode head, int x) {
        ListNode dummy1 = new ListNode(0);
        ListNode dummy2 = new ListNode(0);
        ListNode end1 = dummy1;
        ListNode end2 = dummy2;
        while(head != null){
            if(head.val < x){
                end1.next = head;
                end1 = end1.next;
            }
            else{
                end2.next = head;
                end2 = end2.next;
            }
            head = head.next;
        }
        end2.next = null;
        end1.next = dummy2.next;
        return dummy1.next;
    }


Unique Binary Search Trees II
public List<TreeNode> generateTrees(int n) {
        return dfs(1, n);
    }
   
    public List<TreeNode> dfs(int start, int end){
        List<TreeNode> rst = new ArrayList<TreeNode>();
        if(start > end){
            rst.add(null);
            return rst;
        }
        for(int i=start; i<=end; ++i){
            List<TreeNode> left = dfs(start, i-1);
            List<TreeNode> right = dfs(i+1, end);
            for(int m=0; m<left.size(); ++m)
                for(int n=0; n<right.size(); ++n){
                    TreeNode root = new TreeNode(i);
                    root.left = left.get(m);
                    root.right = right.get(n);
                    rst.add(root);
                }
        }
        return rst;
    }


Triangle
public int minimumTotal(List<List<Integer>> triangle) {
        int m = triangle.size();
        int n = triangle.get(m-1).size();
        int[] dp = new int[n+1];
        for(int i=m-1; i>=0; --i)
            for(int j=0; j<triangle.get(i).size(); ++j){
                dp[j] = Math.min(dp[j], dp[j+1]) + triangle.get(i).get(j);
            }
        return dp[0];
    }


Longest Common Prefix
public String longestCommonPrefix(String[] strs) {
        if(strs.length == 0)
            return "";
        int len = strs[0].length();
        int comm = Integer.MAX_VALUE;
        for(int i=0; i<strs.length; ++i){
            int length = 0;
            for(int j=0; j<len && j<strs[i].length(); ++j){
                if(strs[0].charAt(j) != strs[i].charAt(j))
                    break;
                length++;
            }
            if(length < comm)
                comm = length;
        }
        return strs[0].substring(0,comm);
    }

public String longestCommonPrefix(String[] strs) {
        if(strs == null || strs.length == 0)
            return "";
        int len = 0;
        for(int i=0; i<strs[0].length(); ++i){
            boolean same = true;
            char ch = strs[0].charAt(i);
            for(String str : strs){
                if(i >= str.length() || str.charAt(i) != ch){
                    same = false;
                    break;
                }
            }
            if(!same)
                break;
            len++;
        }
       
        return strs[0].substring(0, len);
    }


Majority Element
public int majorityElement(int[] num) {
        Arrays.sort(num);
        return num[num.length/2];
}

public int majorityElement(int[] nums) {
        int count = 1;
        int num = nums[0];
       
        for(int i=1; i<nums.length; ++i){
            if(count == 0){
                count++;
                num = nums[i];
            }
            else if(nums[i] == num)
                count++;
            else
                count--;
        }
        return num;
    }


Path Sum II
public List<List<Integer>> pathSum(TreeNode root, int sum) {
        List<List<Integer>> rst = new ArrayList<List<Integer>>();
        dfs(rst, new ArrayList<Integer>(), root, sum);
        return rst;
    }
   
    public void dfs(List<List<Integer>> rst, List<Integer> list, TreeNode node, int sum){
        if(node == null)
            return;
        if(node.val == sum && node.left == null && node.right == null){
            list.add(node.val);
            rst.add(new ArrayList<Integer>(list));
            list.remove(list.size()-1);
            return;
        }
        list.add(node.val);
        dfs(rst, list, node.left, sum-node.val);
        dfs(rst, list, node.right, sum-node.val);
        list.remove(list.size()-1);
    }


Intersection of Two Linked Lists
关键是找出差步数
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode pa = headA, pb = headB;
        int lena = 0, lenb = 0;
       
        while(pa != null){
            lena++;
            pa = pa.next;
        }
        while(pb != null){
            lenb++;
            pb = pb.next;
        }
        pa = headA;
        pb = headB;
        if(lena > lenb){
            for(int i=0; i<lena-lenb; ++i)
                pa = pa.next;
        }
        else{
            for(int i=0; i<lenb-lena; ++i)
                pb = pb.next;
        }
        while(pa != null){
            if(pa == pb)
                return pa;
            pa = pa.next;
            pb = pb.next;
        }
        return null;
    }


a clean solution:
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode currA = headA;
        ListNode currB = headB;
        while(currA != currB){
            if(currA == null)
                currA = headB;
            else
                currA = currA.next;
               
            if(currB == null)
                currB = headA;
            else
                currB = currB.next;
        }
        return currA;
    }


Construct Binary Tree from Inorder and Postorder Traversal
public TreeNode buildTree(int[] inorder, int[] postorder) {
        return build(inorder, 0, inorder.length-1, postorder, 0, postorder.length-1);
    }
   
    public TreeNode build(int[] inorder, int lin, int rin, int[] postorder, int lpost, int rpost){
        if(lin > rin || lpost > rpost)
            return null;
       
        int count = 0;
        for(int i=0; i<rin-lin+1; ++i){
            if(inorder[lin+i] == postorder[rpost])
                break;
            ++count;
        }
        TreeNode root = new TreeNode(postorder[rpost]);
        root.left = build(inorder, lin, lin+count-1, postorder, lpost, lpost+count-1);
        root.right = build(inorder, lin+count+1, rin, postorder, lpost+count, rpost-1);
        return root;
    }


Binary Tree Zigzag Level Order Traversal
public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
        Stack<TreeNode> stack = new Stack<TreeNode>();
        Stack<TreeNode> stack2 = new Stack<TreeNode>();
        List<List<Integer>> rst = new ArrayList<List<Integer>>();
       
        stack2.push(root);
        while(!stack.isEmpty() || !stack2.isEmpty()){
            TreeNode node = null;
            List<Integer> list = new ArrayList<Integer>();
            while(!stack2.isEmpty()){
                node = stack2.pop();
                if(node != null){
                    list.add(node.val);
                    stack.push(node.left);
                    stack.push(node.right);
                }
            }
            if(list.size() > 0)
                rst.add(list);
            list = new ArrayList<Integer>();
            while(!stack.isEmpty()){
                node = stack.pop();
                if(node != null){
                    list.add(node.val);
                    stack2.push(node.right);
                    stack2.push(node.left);
                }
            }
            if(list.size() > 0)
                rst.add(list);
        }
        return rst;
    }

public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
        List<List<Integer>> rst = new ArrayList<List<Integer>>();
        if(root == null)
            return rst;
        Queue<TreeNode> q = new LinkedList<TreeNode>();
        q.offer(root);
        int n = 1;
        while(!q.isEmpty()){
            List<Integer> list = new ArrayList<Integer>();
            int count = 0;
            for(int i=0; i<n; ++i){
                TreeNode node = q.poll();
                list.add(node.val);
                if(node.left != null){
                    q.offer(node.left);
                    ++count;
                }
                if(node.right != null){
                    q.offer(node.right);
                    ++count;
                }
            }
            n = count;
            rst.add(list);
        }
       
        for(int i=1; i<rst.size(); i+=2){
            Collections.reverse(rst.get(i));
        }
       
        return rst;
    }


Pow(x, n)
public double pow(double x, int n) {
        if(n == 0)
            return 1;
        double val = pow(x, n/2);
        if(n > 0)
            return n/2*2 == n ? val*val : val*val*x;
        else
            return n/2*2 == n ? val*val : val*val/x;
    }


Reverse Linked List II
public ListNode reverseBetween(ListNode head, int m, int n) {
        ListNode dummy = new ListNode(0);
        dummy.next = head;
       
        ListNode p = dummy;
        ListNode q = head;
        for(int i=1; i<m; ++i){
            p = p.next;
            q = q.next;
        }
       
        for(int i=m; i<n; ++i){
            ListNode node = q.next;
            q.next = q.next.next;
            node.next = p.next;
            p.next = node;
        }
       
        return dummy.next;
    }


N-Queens
public List<String[]> solveNQueens(int n) {
        List<String[]> rst = new ArrayList<String[]>();
       cols = new boolean[n];
        maindiag = new boolean[2*n];
        antidiag = new boolean[2*n];
        dfs(rst, new String[n], 0, n);
        return rst;
    }
   
    private boolean[] cols;
    private boolean[] maindiag;
    private boolean[] antidiag;
   
    public void dfs(List<String[]> rst, String[] strs, int row, int n){
        if(row == n){
            String[] str = new String[n];
            System.arraycopy(strs, 0, str, 0, n);
            rst.add(str);
            return;
        }
       
        for(int i=0; i<n; ++i){
            if(!cols[i] && !maindiag[row+i] && !antidiag[row-i+n-1]){
                char[] chs = new char[n];
                Arrays.fill(chs, '.');
                chs[i] = 'Q';
                cols[i] = true;
                maindiag[row+i] = true;
                antidiag[row-i+n-1] = true;
                strs[row] = String.valueOf(chs);
                dfs(rst, strs, row+1, n);
                cols[i] = false;
                maindiag[row+i] = false;
                antidiag[row-i+n-1] = false;
             }
        }
    }


Maximum Product Subarray
O(1)的DP
public int maxProduct(int[] A) {
        int dppos = 1;
        int dpneg = 1;
        int max = Integer.MIN_VALUE;
        for(int i=0; i<A.length; ++i){
            int poscopy = dppos;
            dppos = Math.max(Math.max(A[i], dppos*A[i]), dpneg*A[i]);
            dpneg = Math.min(Math.min(A[i], poscopy*A[i]), dpneg*A[i]);
            max = Math.max(max, dppos);
        }
        return max;
    }


Linked List Cycle II
public ListNode detectCycle(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;
       
        while(fast != null && fast.next != null){
            slow = slow.next;
            fast = fast.next.next;
            if(fast == slow)
                break;
        }
       
        if(fast == null || fast.next == null)
            return null;
       
        slow = head;
        while(slow != fast){
            slow = slow.next;
            fast = fast.next;
        }
       
        return fast;
    }


Pascal's Triangle
public List<List<Integer>> generate(int numRows) {
        List<List<Integer>> rst = new ArrayList<List<Integer>>();
        List<Integer> list = new ArrayList<Integer>();
        if(numRows == 0)
            return rst;
        for(int i=1; i<=numRows; ++i){
            for(int j=list.size()-1; j>0; --j)
                list.set(j, list.get(j)+list.get(j-1));
            list.add(1);
            rst.add(new ArrayList<Integer>(list));
        }
        return rst;
    }


Pascal's Triangle II
滚动list 
public List<Integer> getRow(int rowIndex) {
        List<Integer> list = new ArrayList<Integer>();
        if(rowIndex < 0)
            return list;
        for(int i=0; i<=rowIndex; ++i){
            for(int j=list.size()-1; j>0; --j)
                list.set(j, list.get(j-1)+list.get(j));
            list.add(1);
        }
        return list;
    }


3Sum Closest
先排序 再左右夹逼
public int threeSumClosest(int[] num, int target) {
        Arrays.sort(num);
        int sum = 0;
        int mingap = Integer.MAX_VALUE;
        for(int i=0; i<num.length-2; ++i){
            int left = i+1;
            int right = num.length-1;
            while(left < right){
                int val = num[i] + num[left] + num[right];
                int gap = Math.abs(val - target);
                if(gap < mingap){
                    mingap = gap;
                    sum = val;
                }
                if(val > target)
                    right--;
                else
                    left++;
            }
        }
        return sum;
    }


Construct Binary Tree from Preorder and Inorder Traversal
public TreeNode buildTree(int[] preorder, int[] inorder) {
        return buildTree(preorder, 0, preorder.length-1, inorder, 0, inorder.length-1);
    }
   
    private TreeNode buildTree(int[] pre, int pl, int pr, int[] ino, int il, int ir){
        if(pl > pr)
            return null;
        TreeNode node = new TreeNode(pre[pl]);
        int count = 0;
        for(int i=il; i<=ir; ++i){
            if(ino[i] == pre[pl])
                break;
            ++count;
        }
        node.left = buildTree(pre, pl+1, pl+count, ino, il, il+count-1);
        node.right = buildTree(pre, pl+count+1, pr, ino, il+count+1, ir);
        return node;
    }


Gas Station
public int canCompleteCircuit(int[] gas, int[] cost) {
        int total = 0;
        int sum = 0;
        int index = 0;
        for(int i=0; i<gas.length; ++i){
            total += gas[i]-cost[i];
            sum += gas[i]-cost[i];
            if(sum < 0){
                sum = 0;
                index = i+1;
            }
        }
        return total >= 0 ? index : -1;
    }


Palindrome Partitioning
有没有更好的解法
public List<List<String>> partition(String s) {
        List<List<String>> rst = new ArrayList<List<String>>();
        if(s == null || s.length() == 0)
            return rst;
        partition(rst, new ArrayList<String>(), s, 0);
        return rst;
    }
   
    public void partition(List<List<String>> rst, List<String> list, String s, int n){
        if(n == s.length()){
            rst.add(new ArrayList<String>(list));
            return;
        }
       
        for(int i=n+1; i<=s.length(); ++i){
            String sub = s.substring(n, i);
            if(isPalindrome(sub)){
                list.add(sub);
                partition(rst, list, s, i);
                list.remove(list.size()-1);
            }
        }
    }
   
    public boolean isPalindrome(String s){
        int i=0;
        int j=s.length()-1;
        while(i<=j){
            if(s.charAt(i++) != s.charAt(j--))
                return false;
        }
        return true;
    }



Count and Say
public String countAndSay(int n) {
        String rst = new String();
        if(n <= 0)
            return rst;
        rst = "1";
       
        for(int i=1; i<n; ++i){
            StringBuilder sb = new StringBuilder();
            for(int j=0; j<rst.length(); ++j){
                int count = 1;
                while(j+1 < rst.length() && rst.charAt(j) == rst.charAt(j+1)){
                    ++j;
                    ++count;
                }
                sb.append(""+count);
                sb.append(rst.charAt(j));
            }
            rst = sb.toString();
        }
        return rst;
    }


Edit Distance
public int minDistance(String word1, String word2) {
        int[][] dp = new int[word1.length()+1][word2.length()+1];
        dp[0][0] = 0;
        for(int i=1; i<=word1.length(); ++i)
            dp[i][0] = i;
        for(int i=1; i<=word2.length(); ++i)
            dp[0][i] = i;
           
        for(int i=1; i<=word1.length(); ++i)
            for(int j=1; j<=word2.length(); ++j){
                int min = Math.min(dp[i-1][j], dp[i][j-1])+1;
                if(word1.charAt(i-1) == word2.charAt(j-1))
                    dp[i][j] = Math.min(min, dp[i-1][j-1]);
                else
                    dp[i][j] = Math.min(min, dp[i-1][j-1]+1);
            }
        return dp[word1.length()][word2.length()];
    }


Insertion Sort List
链表单列出来
public ListNode insertionSortList(ListNode head) {
        ListNode dummy = new ListNode(0);
        dummy.next = null;
       
        while(head != null){
            ListNode curr = dummy;
            while(curr.next != null && curr.next.val < head.val)
                curr = curr.next;
            ListNode temp = curr.next;
            ListNode next = head.next;
            curr.next = head;
            head.next = temp;
            head = next;
        }
        return dummy.next;
    }


Permutations II
public List<List<Integer>> permuteUnique(int[] nums) {
        List<List<Integer>> rst = new ArrayList<List<Integer>>();
        if(nums == null || nums.length == 0)
            return rst;
        Arrays.sort(nums);
        boolean[] used = new boolean[nums.length];
        dfs(rst, new ArrayList<Integer>(), used, nums);
        return rst;
    }
   
    private void dfs(List<List<Integer>> rst, List<Integer> list, boolean[] used, int[] nums){
        if(list.size() == nums.length){
            rst.add(new ArrayList<Integer>(list));
            return;
        }
       
        int pre = nums[0]-1;
        for(int i=0; i<nums.length; ++i){
            if(!used[i] && (i == 0 || nums[i] != pre)){
                pre = nums[i];
                used[i] = true;
                list.add(pre);
                dfs(rst, list, used, nums);
                list.remove(list.size()-1);
                used[i] = false;
            }
        }
    }


Add Binary
public String addBinary(String a, String b) {
        StringBuilder sb = new StringBuilder();
        int carry = 0;
        int ida = a.length()-1;
        int idb = b.length()-1;
       
        while(ida >=0 || idb >= 0){
            if(ida < 0){
                int val = carry + (b.charAt(idb--)-'0');
                sb.append(val%2);
                carry = val/2;
            }
            else if(idb < 0){
                int val = carry + (a.charAt(ida--)-'0');
                sb.append(val%2);
                carry = val/2;
            }
            else{
                int val = carry + (b.charAt(idb--)-'0') + (a.charAt(ida--)-'0');
                sb.append(val%2);
                carry = val/2;
            }
        }
        if(carry > 0)
            sb.append(carry);
        return sb.reverse().toString();
    }


Combination Sum II
public List<List<Integer>> combinationSum2(int[] num, int target) {
        List<List<Integer>> rst = new ArrayList<List<Integer>>();
        Arrays.sort(num);
        comb(rst, new ArrayList<Integer>(), num, 0, target);
        return rst;
    }
   
    public void comb(List<List<Integer>> rst, List<Integer> list, int[] num, int n, int target){
        if(target == 0){
            rst.add(new ArrayList<Integer>(list));
            return;
        }
       
        if(n >= num.length || num[n] > target)
            return;
       
        int idx = n;
        while(idx+1 < num.length && num[idx+1] == num[n])
            ++idx;
       
        comb(rst, list, num, idx+1, target);
        list.add(num[n]);
        comb(rst, list, num, n+1, target-num[n]);
        list.remove(list.size()-1);
    }

public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        List<List<Integer>> rst = new ArrayList<List<Integer>>();
        if(candidates == null)
            return rst;
        Arrays.sort(candidates);
        dfs(rst, new ArrayList<Integer>(), candidates, target, 0);
        return rst;
    }
   
    private void dfs(List<List<Integer>> rst, List<Integer> list, int[] nums, int target, int k){
        if(target == 0){
            rst.add(new ArrayList<Integer>(list));
            return;
        }
       
        for(int i=k; i<nums.length; ++i){
            if(nums[i] > target)
                break;
            if(i==k || nums[i] != nums[i-1]){
                list.add(nums[i]);
                dfs(rst, list, nums, target-nums[i], i+1);
                list.remove(list.size()-1);
            }
        }
    }


Jump Game II
public int jump(int[] A) {
        int step = 0;
        int max = -1;
        int area = 0;
        for(int i=0; i<A.length; ++i){
            if(i > area){
                area = max;
                step++;
                max = -1;
            }
            if(A[i]+i > max)
                max = A[i] + i;
        }
        return step;
    }

public int jump(int[] nums) {
        if(nums == null || nums.length <= 1)
            return 0;
       
        int steps = 0;
        int fast = 0;
        int p = 0;
        int q =0;
        while(p <= q){
            fast = Math.max(fast, p+nums[p]);
            if(p == q){
                q = fast;
                steps++;
                if(q >= nums.length-1)
                    break;
            }
            p++;
        }
       
        return q >= nums.length-1 ? steps : -1;
    }


Remove Duplicates from Sorted List II
public ListNode deleteDuplicates(ListNode head) {
        if(head == null || head.next == null)
            return head;
       
        if(head.val != head.next.val){
            head.next = deleteDuplicates(head.next);
            return head;
        }
       
        while(head.next != null && head.val == head.next.val)
            head = head.next;
        return deleteDuplicates(head.next);
    }


Group Anagrams
public List<List<String>> groupAnagrams(String[] strs) {
        Arrays.sort(strs);
        Map<String, List<String>> map = new HashMap<String, List<String>>();
       
        for(String str : strs){
            String key = getKey(str);
            if(!map.containsKey(key)){
                map.put(key, new ArrayList<String>());
            }
            map.get(key).add(str);
        }
       
        List<List<String>> rst = new ArrayList<List<String>>();
        for(List<String> list : map.values())
            rst.add(list);
       
        return rst;
    }
   
    private String getKey(String str){
        char[] chs = str.toCharArray();
        Arrays.sort(chs);
        return String.valueOf(chs);
    }


Word Search
public boolean exist(char[][] board, String word) {
        int m = board.length;
        int n = board[0].length;
        boolean[][] used = new boolean[m][n];
        for(int i=0; i<m; ++i)
            for(int j=0; j<n; ++j)
                if(exist(board, used, word, "", i, j))
                    return true;
        return false;
    }
   
    private boolean exist(char[][] board, boolean[][] used, String word, String str, int x, int y){
        if(str.equals(word))
            return true;
        if(x<0 || x>=board.length || y<0 || y >= board[0].length ||
            used[x][y] || board[x][y] != word.charAt(str.length()))
            return false;
       
       
        used[x][y] = true;
        if(exist(board, used, word, str+board[x][y], x-1, y) ||
            exist(board, used, word, str+board[x][y], x+1, y) ||
            exist(board, used, word, str+board[x][y], x, y-1) ||
            exist(board, used, word, str+board[x][y], x, y+1))
            return true;
        used[x][y] = false;
        return false;
    }


Copy List with Random Pointer
public RandomListNode copyRandomList(RandomListNode head) {
        if(head == null)
            return null;
           
        RandomListNode curr = head;
        while(curr != null){
            RandomListNode next = new RandomListNode(curr.label);
            next.next = curr.next;
            curr.next = next;
            curr = next.next;
        }
       
        curr = head;
        while(curr != null){
            curr.next.random = curr.random == null ? null : curr.random.next;
            curr = curr.next.next;
        }
       
        curr = head;
        RandomListNode newhead = curr.next;
        while(curr != null){
            RandomListNode nd = curr.next;
            curr.next = nd.next;
            nd.next = nd.next == null ? null : nd.next.next;
            curr = curr.next;
        }
       
        return newhead;
    }


Clone Graph
public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) {
        Map<Integer, UndirectedGraphNode> map = new HashMap<Integer, UndirectedGraphNode>();
        return cloneNode(node, map);
    }
   
    private UndirectedGraphNode cloneNode(UndirectedGraphNode node, Map<Integer, UndirectedGraphNode> map){
        if(node == null)
            return null;
        if(map.containsKey(node.label))
            return map.get(node.label);
           
        UndirectedGraphNode cnode = new UndirectedGraphNode(node.label);
        map.put(node.label, cnode);
        for(UndirectedGraphNode nb : node.neighbors)
            cnode.neighbors.add(cloneNode(nb, map));

        return cnode;
    }


Validate Binary Search Tree
publicboolean isValidBST(TreeNode root){return isValidBST(root,Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);}
 
publicboolean isValidBST(TreeNode p, double min, double max){if(p==null)returntrue;
 
    if(p.val<= min || p.val>= max)returnfalse;
 
    return isValidBST(p.left, min, p.val)&& isValidBST(p.right, p.val, max);}

Add Two Numbers
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode dummy = new ListNode(0);
        ListNode curr = dummy;
        int carry = 0;
       
        while(l1 != null || l2 != null){
            int val = 0;
            if(l1 == null){
                val = l2.val + carry;
                l2 = l2.next;
            }
            else if(l2 == null){
                val = l1.val + carry;
                l1 = l1.next;
            }
            else{
                val = l1.val + l2.val + carry;
                l1 = l1.next;
                l2 = l2.next;
            }
            curr.next = new ListNode(val % 10);
            carry = val / 10;
            curr = curr.next;
        }
        if(carry > 0)
            curr.next = new ListNode(carry);
        return dummy.next;
    }



Two Sum
public int[] twoSum(int[] numbers, int target) {
        Map<Integer, Integer> map = new HashMap<Integer, Integer>();
        int[] rst = new int[2];
       
        for(int i=0; i<numbers.length; ++i)
            map.put(numbers[i], i);  // 如果有重复的话 新index会覆盖原index 这是合理的
        for(int i=0; i<numbers.length; ++i)
            if(map.containsKey(target-numbers[i]) && map.get(target-numbers[i]) != i){
                rst[0] = i+1;
                rst[1] = map.get(target-numbers[i])+1;
                break;
            }
        return rst;
    }


Word Break
dp
public boolean wordBreak(String s, Set<String> dict) {
        if(s == null || s.length() == 0)
            return true;
       
        boolean[] dp = new boolean[s.length()+1];
        dp[0] = true;
       
        for(int i=1; i<=s.length(); ++i){
            for(int j=0; j<i; ++j)
                if(dp[j] && dict.contains(s.substring(j,i))){
                    dp[i] = true;
                    break;
                }
        }
        return dp[s.length()];
    }

public boolean wordBreak(String s, Set<String> wordDict) {
        if(s == null || s.length() == 0)
            return true;
       
        boolean[] dp = new boolean[s.length()+1];
        dp[0] = true;
        for(int i=1; i<=s.length(); ++i){
            for(int j=i-1; j>=0; --j){
                String str = s.substring(j, i);
                if(wordDict.contains(str) && dp[j]){
                    dp[i] = true;
                    break;
                }
            }
        }
       
        return dp[s.length()];
    }



3Sum
public List<List<Integer>> threeSum(int[] num) {
        List<List<Integer>> rst = new ArrayList<List<Integer>>();
        if(num.length < 3)
            return rst;
        Arrays.sort(num);
        for(int i=0; i<num.length-2; ++i){
            int left = i+1;
            int right = num.length-1;
            while(left < right){
                if(num[i]+num[left]+num[right] < 0)
                    ++left;
                else if(num[i]+num[left]+num[right] > 0)
                    --right;
                else{
                    List<Integer> list = new ArrayList<Integer>();
                    list.add(num[i]); list.add(num[left]); list.add(num[right]);
                    rst.add(list);
                    ++left;
                    --right;
                    while(left<right && num[left] == num[left-1])
                        ++left;
                    while(left<right && num[right] == num[right+1])
                        --right;
                }
            }
            while(i+1 < num.length-2 && num[i] == num[i+1])
                ++i;  // *****************************
        }
        return rst;
    }


Decode Ways
public int numDecodings(String s) {
        if(s == null || s.length() == 0)
            return 0;
        int[] dp = new int[s.length()+1];
        dp[0] = 1;
        dp[1] = s.charAt(0)=='0' ? 0 : 1;
        for(int i=2; i<=s.length(); ++i){
            if(s.charAt(i-1) == '0'){
          if(s.charAt(i-2) == '0' || s.charAt(i-2) > '2')
           return 0;
          dp[i] = dp[i-2];
         }
         else{
          if(s.charAt(i-2) == '0' || Integer.parseInt(s.substring(i-2, i)) > 26)
           dp[i] = dp[i-1];
          else
           dp[i] = dp[i-1] + dp[i-2];
         }
        }
        return dp[s.length()];
    }


Word Ladder
public int ladderLength(String start, String end, Set<String> dict) {
        int rst = 1;
        Set<String> visited = new HashSet<String>();
        Queue<String> queue = new LinkedList<String>();
        int count = 0;
        int num = 1;
        queue.offer(start);
        visited.add(start);
        while(!queue.isEmpty()){
            String node = queue.poll();
            --num;
           
            if(node.equals(end))
                return rst;
           
            char[] chs = node.toCharArray();
            for(int i=0; i<chs.length; ++i){
                char ch = chs[i];
                for(int j=0; j<26; ++j){
                    chs[i] = (char)('a'+j);
                    if(chs[i] == ch) continue;
                    String nb = String.valueOf(chs);
                    if(!visited.contains(nb) && dict.contains(nb)){
                        queue.offer(nb);
                        visited.add(nb);
                        ++count;
                    }
                    chs[i] = ch;
                }
            }
           
            if(num == 0){
                num = count;
                count = 0;
                ++rst;
            }
        }
        return 0;
    }



Excel Sheet Column Title
public String convertToTitle(int n) {
        String rst = "";
        while(n > 0){
            rst = (char)('A' + (n-1)%26) + rst;
            n = (n-1)/26;
        }
        return rst;
    }



LRU Cache
public LRUCache(int capacity) {
        map = new HashMap<Integer, Node>();
        head = new Node(-1, -1);
        tail = head;
        for(int i=1; i<capacity; ++i){
            tail.next = new Node(-1, -1);
            tail.next.prev = tail;
            tail = tail.next;
        }
        head.prev = tail;
        tail.next = head;
    }
   
    public int get(int key) {
        if(!map.containsKey(key))
            return -1;
        detach(map.get(key));
        attach(map.get(key));
        return map.get(key).value;
    }
   
    public void set(int key, int value) {
        if(map.containsKey(key)){
            map.get(key).value = value;
            detach(map.get(key));
            attach(map.get(key));
            return;
        }
        Node nd = new Node(key, value);
        map.put(key, nd);
        attach(nd);
        map.remove(tail.key);
        detach(tail);
    }
   
    private void detach(Node nd){
        nd.prev.next = nd.next;
        nd.next.prev = nd.prev;
        if(nd == tail)
            tail = nd.prev;
        if(nd == head)
            head = nd.next;
    }
   
    private void attach(Node nd){
        tail.next = nd;
        nd.prev = tail;
        nd.next = head;
        head.prev = nd;
        head = nd;
    }
   
    private Map<Integer, Node> map;
    private Node head;
    private Node tail;
   
    class Node{
        public int key;
        public int value;
        public Node prev;
        public Node next;
       
        public Node(int key, int value){
            this.key = key;
            this.value = value;
        }
    }



Convert Sorted List to Binary Search Tree
private ListNode list;
   
    public TreeNode sortedListToBST(ListNode head) {
        int n = 0;
        ListNode curr = head;
        while(curr != null){
            curr = curr.next;
            ++n;
        }
        list = head;
        return sortedListToBST(0, n-1);
    }
   
    private TreeNode sortedListToBST(int start, int end){
        if(start > end)
            return null;
        int mid = start + (end-start)/2;
        TreeNode left = sortedListToBST(start, mid-1);
        TreeNode root = new TreeNode(list.val);
        list = list.next;
        root.left = left;
        root.right = sortedListToBST(mid+1, end);
        return root;
    }


Permutation Sequence
public String getPermutation(int n, int k) {
        List<Integer> nums = new ArrayList<Integer>();
        int fac = 1;
       
        for(int i=1; i<=n; ++i){
            nums.add(i);
            fac *= i;
        }
        k--;
        String rst = "";
       
        for(int i=0; i<n; i++){
            fac /= n-i;
            int choosed = k / fac;
            rst += nums.get(choosed);
           
            nums.remove(choosed);
            k = k % fac;
        }
 
        return rst;
    }


Longest Substring Without Repeating Characters
public int lengthOfLongestSubstring(String s) {
        int rst = 0;
        Map<Character, Integer> map = new HashMap<Character, Integer>();
       
        int left = -1;
        int right = 0;
        while(right < s.length()){
            char ch = s.charAt(right);
            if(!map.containsKey(ch) || map.get(ch) < left){
                map.put(ch, right);
                if(right-left > rst)
                    rst = right-left;
            }
            else{
                left = map.get(ch);
                map.put(ch, right);
            }
            ++right;
        }
        return rst;
    }



Candy
public int candy(int[] ratings) {
  int[] candy = new int[ratings.length];
 
  Arrays.fill(candy, 1);
 
  for(int i=1; i<candy.length; ++i)
      if(ratings[i] > ratings[i-1] && candy[i] <= candy[i-1])
          candy[i] = candy[i-1]+1;
         
  for(int i=candy.length-2; i>=0; --i)
      if(ratings[i] > ratings[i+1] && candy[i] <= candy[i+1])
          candy[i] = candy[i+1]+1;
 
  int num = 0;
  for(int i=0; i<candy.length; i++)
   num += candy[i];
 
  return num;
    }


Next Permutation
public void nextPermutation(int[] nums) {
        int index = -1;
        for(int i=nums.length-1; i>0; --i)
            if(nums[i] > nums[i-1]){
                index = i-1;
                break;
            }
         if(index == -1){
            Arrays.sort(nums);
            return;
         }
         
         for(int i=nums.length-1; i>index; --i){
             if(nums[i] > nums[index]){
                 int temp = nums[i];
                 nums[i] = nums[index];
                 nums[index] = temp;
                 break;
             }
         }
         
         Arrays.sort(nums, index+1, nums.length);
    }



Reverse Nodes in k-Group
public ListNode reverseKGroup(ListNode head, int k) {
        if(head == null || head.next == null || k <= 1)
            return head;
       
        ListNode curr = head;
        int n = 1;
        while(n++ < k){
            curr = curr.next;
            if(curr == null)
                return head;
        }
        curr.next = reverseKGroup(curr.next, k);
        ListNode end = curr;
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        while(dummy.next != end){
            ListNode temp = curr.next;
            curr.next = dummy.next;
            dummy.next = dummy.next.next;
            curr.next.next = temp;
        }
       
        return dummy.next;
    }



Distinct Subsequences
public int numDistinct(String S, String T) {
        int[][] dp = new int[T.length()+1][S.length()+1];
       
        for(int i=0; i<dp[0].length; ++i)
            dp[0][i] = 1;
           
        for(int i=1; i<dp.length; ++i)
            for(int j=1; j<dp[i].length; ++j){
                if(S.charAt(j-1) == T.charAt(i-1))
                    dp[i][j] = dp[i-1][j-1] + dp[i][j-1];
                else
                    dp[i][j] = dp[i][j-1];
            }
        return dp[T.length()][S.length()];
    }


Recover Binary Search Tree
private TreeNode first, second;
    boolean find;
   
    public void recoverTree(TreeNode root) {
        first = new TreeNode(Integer.MIN_VALUE);
        find = false;
       
        recover(root);
       
        if(first != null && second != null){
            int v = first.val;
            first.val = second.val;
            second.val = v;
        }
    }
   
    public void recover(TreeNode node){
        if(node == null)
            return;
        recover(node.left);
        if(node.val < first.val){
            second = node;
            find = true;
        }
        else if(!find){
            first = node;
        }
        recover(node.right);
    }


TreeNode first;
    TreeNode second;
    TreeNode iter;
   
    public void recoverTree(TreeNode root) {
        inorder(root);
        if(first != null && second != null){
            int temp = first.val;
            first.val = second.val;
            second.val = temp;
        }
    }
   
    private void inorder(TreeNode node){
        if(node == null)
            return;
       
        inorder(node.left);
       
        if(iter != null && node.val < iter.val){
            if(first == null){
                first = iter;
            }
            second = node;
        }
       
        iter = node;
        inorder(node.right);
    }


Reverse Words in a String
split() 会有""结果
public String reverseWords(String s) {
        String[] tokens = s.trim().split(" ");
        StringBuilder rst = new StringBuilder();
        
        for(int i=tokens.length-1; i>=0; --i){
            if(tokens[i] == null || tokens[i].length()==0)
                continue;
            rst.append(tokens[i]+" ");
        }
        
        return rst.toString().trim();
    }


First Missing Positive
public int firstMissingPositive(int[] A) {
        for(int i=0; i<A.length;){
            if(A[i] < 1 || A[i] > A.length || A[A[i]-1] == A[i]){
                ++i;
                continue;
            }
            int v = A[A[i]-1];
            A[A[i]-1] = A[i];
            A[i] = v;
        }
        for(int i=0; i<A.length; ++i){
            if(A[i] != i+1)
                return i+1;
        }
        return A.length+1;
    }


Largest Rectangle in Histogram
public int largestRectangleArea(int[] height) {
        int max = 0;
        Stack<Integer> stack = new Stack<Integer>();
        for(int i=0; i<height.length; ++i){
            if(stack.empty() || height[i] > height[stack.peek()]){
                stack.push(i);
                continue;
            }
            while(!stack.empty() && height[i] <= height[stack.peek()]){
                int ind = stack.pop();
                if(stack.empty())
                    max = Math.max(max, height[ind] * (i-0));
                else
                    max = Math.max(max, height[ind] * (i-stack.peek()-1));
            }
            stack.push(i);
        }
       
        while(!stack.empty()){
            int ind = stack.pop();
            if(stack.empty())
                max = Math.max(max, height[ind] * height.length);
            else
                max = Math.max(max, height[ind] * (height.length-stack.peek()-1));
        }
       
        return max;
    }


Best Time to Buy and Sell Stock III
public int maxProfit(int[] prices) {
        if(prices.length < 2)
            return 0;
           
        int[] left = new int[prices.length];
        int[] right = new int[prices.length];
       
        int min = prices[0];
        int p = 0;
        for(int i=0; i<prices.length; ++i){
            if(prices[i] < min)
                min = prices[i];
            p = Math.max(p, prices[i]-min);
            left[i] = p;
        }
        int max = prices[prices.length-1];
        p = 0;
        for(int i=prices.length-1; i>=0; --i){
            if(prices[i] > max)
                max = prices[i];
            p = Math.max(p, max-prices[i]);
            right[i] = p;
        }
       
        max = 0;
        for(int i=0; i<prices.length; ++i)
            max = Math.max(max, left[i] + right[i]);
        return max;
    }


Rotate List
public ListNode rotateRight(ListNode head, int n) {
        if(head == null)
            return head;
        int num = 1;
        ListNode curr = head;
        while(curr.next != null){
            curr = curr.next;
            ++num;
        }
        curr.next = head;
        for(int i=0; i<num-n%num; ++i)
            curr = curr.next;
        head = curr.next;
        curr.next = null;
        return head;
    }


Sort List
快慢指针找中间结点!


Simplify Path
public String simplifyPath(String path) {
        Stack<String> stack = new Stack<String>();
        String[] tokens = path.split("/");
       
        for(int i=0; i<tokens.length; ++i){
            if(tokens[i].equals(".") || tokens[i].equals(""))
                continue;
            if(tokens[i].equals("..")){
                if(!stack.empty()) stack.pop();
            }
            else
                stack.push(tokens[i]);
        }
       
        StringBuilder sb = new StringBuilder();
        while(!stack.empty())
            sb.insert(0, "/"+stack.pop());
           
        return sb.length()==0 ? "/" : sb.toString();
    }


4Sum
public List<List<Integer>> fourSum(int[] num, int target) {
        List<List<Integer>> rst = new ArrayList<List<Integer>>();
        if(num.length < 4)
            return rst;
        Arrays.sort(num);
        for(int i=0; i<num.length-3; ++i){
            if(i>0 && num[i] == num[i-1])
                continue;
            for(int j=i+1; j<num.length-2; ++j){
                if(j>i+1 && num[j] == num[j-1])
                    continue;
                int left = j+1;
                int right = num.length-1;
                while(left < right){
                    if(num[i] + num[j] + num[left] + num[right] == target){
                        List<Integer> list = new ArrayList<Integer>();
                        list.add(num[i]); list.add(num[j]);
                        list.add(num[left]); list.add(num[right]);
                        rst.add(list);
                        ++left;
                        while(left < right && num[left] == num[left-1])
                            ++left;
                        --right;
                        while(left < right && num[right] == num[right+1])
                            --right;
                    }
                    else if(num[i] + num[j] + num[left] + num[right] < target){
                        ++left;
                        //while(left < right && num[left] == num[left-1])
                         //   ++left;
                    }
                    else{
                        --right;
                        //while(left < right && num[right] == num[right+1])
                        //    --right;
                    }
                }
            }
        }
        return rst;
    }


Sudoku Solver
public void solveSudoku(char[][] board) {
        dfs(board);
    }
   
    private boolean dfs(char[][] board){
        for(int i=0; i<9; ++i)
            for(int j=0; j<9; ++j){
                if(board[i][j] != '.')
                    continue;
                for(int x=1; x<10; ++x){
                    if(isValid(board, i, j, x)){
                        board[i][j] = (char)('0'+x);
                        if(dfs(board))
                            return true;
                        board[i][j] = '.';
                    }
                }
                return false;
            }
        return true;
    }
   
    private boolean isValid(char[][] board, int x, int y, int v){
        for(int i=0; i<9; ++i)
            if(i!=x && board[i][y]-'0' == v || i!=y && board[x][i]-'0' == v)
                return false;
        for(int i=0; i<3; ++i)
            for(int j=0; j<3; ++j){
                int row = x/3*3+i;
                int col = y/3*3+j;
                if(row != x && col != y && board[row][col]-'0' == v)
                    return false;
            }
        return true;
    }



Longest Palindromic Substring
public String longestPalindrome(String s) {
        if(s == null || s.length()==0)
            return s;
        boolean[][] p = new boolean[s.length()][s.length()];
        int maxLen = 1;
        int start = 0;
        for(int i=0; i<s.length(); ++i){
            p[i][i] = true;
            for(int j=i-1; j>=0; --j){
                p[j][i] = (s.charAt(i)==s.charAt(j)) && (j+1 == i || p[j+1][i-1]);
                if(p[j][i] && i-j+1 > maxLen){
                    maxLen = i-j+1;
                    start = j;
                }
            }
        }
        return s.substring(start, start+maxLen);
    }


Merge k Sorted Lists
public ListNode mergeKLists(List<ListNode> lists) {
        if(lists == null || lists.size() == 0)
            return null;
        if(lists.size() == 1)
            return lists.get(0);
       
        int mid = lists.size()/2;
        List<ListNode> half = new ArrayList<ListNode>();
        while(mid-- > 0){
            half.add(lists.get(0));
            lists.remove(0);
        }
       
        ListNode left = mergeKLists(lists);
        ListNode right = mergeKLists(half);
        ListNode dummy = new ListNode(0);
        ListNode curr = dummy;
        while(left != null && right != null){
            if(left.val < right.val){
                curr.next = left;
                left = left.next;
            }
            else{
                curr.next = right;
                right = right.next;
            }
            curr = curr.next;
        }
        while(left != null){
            curr.next = left;
            curr = curr.next;
            left = left.next;
        }
        while(right != null){
            curr.next = right;
            curr = curr.next;
            right = right.next;
        }
       
        return dummy.next;
    }


Longest Valid Parentheses
public int longestValidParentheses(String s) {
        if(s == null || s.length() <= 1)
            return 0;
       
        int[] dp = new int[s.length()];
        int len = 0;
       
        for(int i=1; i<s.length(); ++i){
            if(s.charAt(i) == '(')
                continue;
            if(s.charAt(i-1) == '('){
                dp[i] = i-2 >= 0 ? dp[i-2]+2 : 2;
            }
            else{
                int v = dp[i-1];
                if(i-1-v >= 0 && s.charAt(i-1-v) == '('){
                    dp[i] = i-2-v >= 0 ? v+2+dp[i-2-v] : v+2;     // ()(())
                }
            }
           
            len = Math.max(len, dp[i]);
        }
       
        return len;
    }


Binary Tree Maximum Path Sum
public int maxPathSum(TreeNode root) {
        max = Integer.MIN_VALUE;
        dfs(root);
        return max;
    }
   
    private int max;
   
    private int dfs(TreeNode node){
        if(node == null)
            return 0;
           
        int left = dfs(node.left);
        int right = dfs(node.right);
       
        int v = node.val;
        if(left > 0)
            v += left;
        if(right > 0)
            v += right;
        max = Math.max(v, max);
       
        if(left < 0 && right < 0)
            return node.val;
        return left>right ? left+node.val : right+node.val;
    }


Reorder List
public void reorderList(ListNode head) {
        if(head == null || head.next == null || head.next.next == null)
            return;
       
        ListNode fast = head;
        ListNode slow = head;
        while(fast.next != null && fast.next.next != null){
            fast = fast.next.next;
            slow = slow.next;
        }
        ListNode mid = slow.next;
        slow.next = null;
       
        if(fast.next != null) fast = fast.next;
        while(mid != fast){
            slow = fast.next;
            fast.next = mid;
            mid = mid.next;
            fast.next.next = slow;
        }
       
        ListNode dummy = new ListNode(0);
        ListNode curr = dummy;
        while(head != null || mid != null){
            if(head != null){
                curr.next = head;
                head = head.next;
                curr = curr.next;
            }
            if(mid != null){
                curr.next = mid;
                mid = mid.next;
                curr = curr.next;
            }
        }
       
        head = dummy.next;
    }



Min Stack
private List<Integer> stack = new ArrayList<Integer>();
    private List<Integer> minStack = new ArrayList<Integer>();
   
    public void push(int x) {
        stack.add(x);
        if(minStack.isEmpty() || x <= minStack.get(minStack.size()-1))
            minStack.add(x);
    }

    public void pop() {
        if(stack.isEmpty())
            return;
        if(stack.get(stack.size()-1).equals(minStack.get(minStack.size()-1)))
            minStack.remove(minStack.size()-1);
        stack.remove(stack.size()-1);
    }

    public int top() {
        if(stack.isEmpty())
            return 0;
        return stack.get(stack.size()-1);
    }

    public int getMin() {
        if(minStack.isEmpty())
            return 0;
        return minStack.get(minStack.size()-1);
    }


Evaluate Reverse Polish Notation
public int evalRPN(String[] tokens) {
        Stack<Integer> stack = new Stack<Integer>();
        for(String str : tokens){
            if(str.equals("+")){
                int y = stack.pop();
                int x = stack.pop();
                stack.push(x+y);
            }
            else if(str.equals("*")){
                int y = stack.pop();
                int x = stack.pop();
                stack.push(x*y);
            }
            else if(str.equals("/")){
                int y = stack.pop();
                int x = stack.pop();
                stack.push(x/y);
            }
            else if(str.equals("-")){
                int y = stack.pop();
                int x = stack.pop();
                stack.push(x-y);
            }
            else{
                stack.push(Integer.parseInt(str));
            }
        }
        return stack.peek();
    }



Palindrome Partitioning II
public int minCut(String s) {
        if(s == null || s.length() < 2)
            return 0;
           
        boolean[][] p = new boolean[s.length()][s.length()];
        int[] dp = new int[s.length()];
        p[0][0] = true;
        for(int i=1; i<s.length(); ++i){
            p[i][i] = true;
            int minc = dp[i-1]+1;
            for(int j=i-1; j>=0; --j){
                if((j == i-1 || p[j+1][i-1] )&& s.charAt(i)==s.charAt(j)){
                    p[j][i] = true;
                    int cut = j == 0 ? 0 : dp[j-1]+1;
                    minc = Math.min(minc, cut);
                }
            }
            dp[i] = minc;
        }
       
        return dp[s.length()-1];
    }


Regular Expression Matching
public boolean isMatch(String s, String p) {
        return isMatch(s, 0, p, 0);
    }
   
    private boolean isMatch(String s, int sl, String p, int pl){
        if(pl == p.length())
            return sl == s.length();
           
        if(pl == p.length()-1 || p.charAt(pl+1) != '*'){
            if(sl == s.length())
                return false;
            return (s.charAt(sl)==p.charAt(pl) || p.charAt(pl)=='.') ? isMatch(s, sl+1, p, pl+1) : false;
        }
        else{
            for(int i=sl; i<s.length(); ++i){
                if(s.charAt(i)!=p.charAt(pl) && p.charAt(pl)!='.')
                    break;
                if(isMatch(s, i+1, p, pl+2))
                    return true;
            }
            return isMatch(s, sl, p, pl+2);
        }
    }


Surrounded Regions
public void solve(char[][] board) {
        if(board == null || board.length==0)
            return;
           
        Stack<Integer> stackr = new Stack<Integer>();
        Stack<Integer> stackc = new Stack<Integer>();
       
        for(int i=0; i<board.length; ++i){
            stackr.push(i);
            stackc.push(0);
            stackr.push(i);
            stackc.push(board[0].length-1);
        }
        for(int i=0; i<board[0].length; ++i){
            stackr.push(0);
            stackc.push(i);
            stackr.push(board.length-1);
            stackc.push(i);
        }
       
        while(!stackr.isEmpty()){
            int r = stackr.pop();
            int c = stackc.pop();
            if(r<0 || r>=board.length || c<0 || c>=board[0].length || board[r][c] != 'O')
                continue;
            board[r][c] = 'Y';
            stackr.push(r+1); stackc.push(c);
            stackr.push(r); stackc.push(c+1);
            stackr.push(r-1); stackc.push(c);
            stackr.push(r); stackc.push(c-1);
        }
       
        for(int i=0; i<board.length; ++i)
            for(int j=0; j<board[0].length; ++j)
                if(board[i][j] == 'O')
                    board[i][j] = 'X';
                else if(board[i][j] == 'Y')
                    board[i][j] = 'O';
       
    }



Wildcard Matching
public boolean isMatch(String s, String p) {
        if(p == null)
            return s == null;
        int i = 0;
        int j = 0;
        int star = -1;
        int mark = -1;
        while(i < s.length()){
            if(j < p.length() && p.charAt(j) == '*'){
                star = j++;
                mark = i;
            }
            else if(j < p.length() && (p.charAt(j) == '?' || p.charAt(j) == s.charAt(i))){
                ++i;
                ++j;
            }
            else if(star != -1){
                j = star + 1;
                i = ++mark;
            }
            else
                return false;
        }
        while(j < p.length() && p.charAt(j)=='*')
            ++j;
        return j == p.length();
    }



Max Points on a Line
public int maxPoints(Point[] points) {
        int max = 0;
        for(int i=0; i<points.length; ++i){
            Map<Double, Integer> map = new HashMap<Double,Integer>();
            int infinity = 1;
            int same = 0;
            int count = 1;
            for(int j=i+1; j<points.length; ++j){
                if(points[i].x == points[j].x && points[i].y == points[j].y){
                    ++same;
                }
                else if(points[i].x == points[j].x){
                    ++infinity;
                    count = Math.max(count, infinity);
                }
                //java里面Object wrapper的Double类型比较0.0和-0.0是按照位比较,
                //符号位的不同在比较时也会被考虑,所以记得把-0.0转换成0.0存储。(但是普通double类型就不会这                        样。。。。)
                else if(points[i].y == points[j].y){
                    if(map.containsKey(0.0))
                        map.put(0.0, map.get(0.0)+1);
                    else
                        map.put(0.0, 2);
                    count = Math.max(count, map.get(0.0));
                }
                else{
                    double key = (double)(points[i].y-points[j].y)/(points[i].x-points[j].x);
                    if(map.containsKey(key))
                        map.put(key, map.get(key)+1);
                    else
                        map.put(key, 2);
                    count = Math.max(count, map.get(key));
                }
            }
            count += same;
            max = Math.max(max, count);
        }
        return max;
    }


Maximal Rectangle
O(n^3)
public int maximalRectangle(char[][] matrix) {
        if(matrix == null || matrix.length == 0)
            return 0;
 int[][] arr = new int[matrix.length][matrix[0].length];
 for(int i=0; i<arr.length; ++i){
  arr[i][0] = Integer.parseInt(String.valueOf(matrix[i][0]));   parseInt 需要String
  for(int j=1; j<arr[0].length; ++j){
   arr[i][j] = matrix[i][j] == '1' ? 1+arr[i][j-1] : 0;
}
}
int max = 0;
for(int i=0; i<arr.length; ++i){
 for(int j=0; j<arr[0].length; ++j){
  int w = arr[i][j];
  for(int h=i; h>=0; --h){
   if(arr[h][j] < w)
    w = arr[h][j];
   max = Math.max(max,w*(i-h+1));
}
}
}
return max;
}



O(n^2)
largestRectangleArea on histogram

public int maximalRectangle(char[][] matrix) {
        if(matrix == null)
            return 0;
        if(matrix.length == 0 || matrix[0].length == 0)
            return 0;
           
        int r = matrix.length;
        int c = matrix[0].length;
       
        int[] height = new int[c];
       
        int area = 0;
       
        for(int i=0; i<r; ++i){
            for(int j=0; j<c; ++j){
                height[j] = matrix[i][j] == '1' ? height[j]+1 : 0;
            }
            area = Math.max(area, largestRectangleArea(height));
        }
        return area;
    }
   
    public int largestRectangleArea(int[] height) {
        int max = 0;
        Stack<Integer> stack = new Stack<Integer>();
        for(int i=0; i<height.length; ++i){
            if(stack.empty() || height[i] > height[stack.peek()]){
                stack.push(i);
                continue;
            }
            while(!stack.empty() && height[i] <= height[stack.peek()]){
                int ind = stack.pop();
                if(stack.empty())
                    max = Math.max(max, height[ind] * (i-0));
                else
                    max = Math.max(max, height[ind] * (i-stack.peek()-1));
            }
            stack.push(i);
        }
       
        while(!stack.empty()){
            int ind = stack.pop();
            if(stack.empty())
                max = Math.max(max, height[ind] * height.length);
            else
                max = Math.max(max, height[ind] * (height.length-stack.peek()-1));
        }
       
        return max;
    }


Multiply Strings
public String multiply(String num1, String num2) {
        StringBuilder sb1 = new StringBuilder(num1);
        StringBuilder sb2 = new StringBuilder(num2);
        sb1.reverse();
        sb2.reverse();
       
        int[] num = new int[num1.length()+num2.length()];
       
        for(int i=0; i<sb1.length(); ++i)
            for(int j=0; j<sb2.length(); ++j){
                num[i+j] += (sb1.charAt(i)-'0')*(sb2.charAt(j)-'0');
            }
           
       
        for(int i=0; i<num.length-1; ++i){
            num[i+1] += num[i]/10;
            num[i] = num[i]%10;
        }
        String rst = "";
        int i=num.length-1;
        while(i>=0 && num[i] == 0)
            i--;
        while(i >=0){
            rst += num[i--];
        }
        return rst.equals("") ? "0" : rst;
    }


Insert Interval
public List<Interval> insert(List<Interval> intervals, Interval newInterval) {
        List<Interval> rst = new ArrayList<Interval>();
        boolean done = false;
        for(Interval curr : intervals){
            if(done){
                rst.add(curr);
            }
            else if(newInterval.end < curr.start){
                rst.add(newInterval);
                rst.add(curr);
                done = true;
            }
            else if(newInterval.start > curr.end){
                rst.add(curr);
            }
            else{
                newInterval.start = Math.min(newInterval.start, curr.start);
                newInterval.end = Math.max(newInterval.end, curr.end);
            }
        }
        if(!done)
            rst.add(newInterval);
        return rst;
    }


Factorial Trailing Zeroes
public int trailingZeroes(int n) {
        int num = 0;
        while(n >= 5){
            num += n/5;
            n /= 5;
        }
        return num;
    }



Maximum Gap
radix sort
public int maximumGap(int[] nums) {
        if(nums.length <= 1)
            return 0;
        Map<Integer, List<Integer>> map = new HashMap<Integer, List<Integer>>();
        for(int x : nums){
            int key = x%10;
            if(!map.containsKey(key))
                map.put(key, new ArrayList<Integer>());
            map.get(key).add(x);
        }
       
        int d = 10;
        for(int i=0; i<9; ++i){
            Map<Integer, List<Integer>> nmap = new HashMap<Integer, List<Integer>>();
            for(List<Integer> list : map.values()){
                for(int x : list){
                    int key = (x/d)%10;
                    if(!nmap.containsKey(key))
                        nmap.put(key, new ArrayList<Integer>());
                    nmap.get(key).add(x);
                }
            }
            map = nmap;
            d *= 10;
        }
       
        int gap = 0;
        int pre = -1;
        for(int j=0; j<10; ++j){
            List<Integer> list = map.get(j);
            if(list == null)
                    continue;
            for(int x : list){
                if(pre == -1){
                    pre = x;
                    continue;
                }
                gap = Math.max(gap, x - pre);
                pre = x;
            }
        }
       
        return gap;
    }


Compare Version Numbers
public int compareVersion(String version1, String version2) {
        String[] v1 = version1.split("[.]");
        String[] v2 = version2.split("[.]");
       
        int len = Math.max(v1.length, v2.length);
        for(int i=0; i<len; ++i){
            if(i >= v1.length){
                if(Integer.parseInt(v2[i]) != 0)
                    return -1;
                continue;
            }
            if(i >= v2.length){
                if(Integer.parseInt(v1[i]) != 0)
                    return 1;
                continue;
            }
            if(Integer.parseInt(v1[i]) > Integer.parseInt(v2[i]))
                return 1;
            if(Integer.parseInt(v1[i]) < Integer.parseInt(v2[i]))
                return -1;
        }
        return 0;
    }


Excel Sheet Column Number
public int titleToNumber(String s) {
        if(s == null || s.length() == 0)
            return 0;
       
        int rst = 0
        for(int i=0; i<s.length(); ++i){
            char ch = s.charAt(i);
            rst = rst*26 + (ch-'A'+1);
        }
       
        return rst;
    }


Binary Search Tree Iterator
public class BSTIterator {
   
    private Stack<TreeNode> stack;
    private TreeNode p;
    public BSTIterator(TreeNode root) {
        p = root;
        stack = new Stack<TreeNode>();
       
        while(p != null){
            stack.push(p);
            p = p.left;
        }
       
    }
    /** @return whether we have a next smallest number */
    public boolean hasNext() {
        return !stack.isEmpty();
    }
    /** @return the next smallest number */
    public int next() {
        TreeNode next = stack.pop();
        p = next.right;
        while(p != null){
            stack.push(p);
            p = p.left;
        }
        return next.val;
    }
}


Dungeon Game
public int calculateMinimumHP(int[][] dungeon) {
        if(dungeon == null || dungeon.length == 0 || dungeon[0].length == 0)
            return 0;
       
        int r = dungeon.length;
        int c = dungeon[0].length;
        int[][] dp = new int[r][c];
       
        dp[r-1][c-1] = Math.max(-dungeon[r-1][c-1]+1, 1);
        for(int i=r-2; i>=0; --i){
            dp[i][c-1] = Math.max(1, dp[i+1][c-1] - dungeon[i][c-1]);
        }
        for(int i=c-2; i>=0; --i){
            dp[r-1][i] = Math.max(1, dp[r-1][i+1] - dungeon[r-1][i]);
        }
       
        for(int i=r-2; i>=0; --i){
            for(int j=c-2; j>=0; --j){
               
                dp[i][j] = Math.max(1, Math.min(dp[i+1][j], dp[i][j+1]) - dungeon[i][j]);
            }
        }
       
        return dp[0][0];
    }


Largest Number
public String largestNumber(int[] nums) {
        String[] strs = new String[nums.length];
  for(int i=0; i<nums.length; ++i)
   strs[i] = "" + nums[i];
  Arrays.sort(strs, new Comp());
 
        String rst = "";
        for(int i=strs.length-1; i>=0; --i)
            rst += strs[i];
       
        return rst.charAt(0) == '0' ? "0" : rst;
    }
   
    public static class Comp implements Comparator<String>{
        public int compare(String a, String b){
            String ab = a + b;
            String ba = b + a;
            return ab.compareTo(ba);
        }
    }

public String largestNumber(int[] nums) {
        Integer[] A = new Integer[nums.length];
        for(int i=0; i<nums.length; ++i)
            A[i] = nums[i];
        Arrays.sort(A, new Comp());
        String rst = "";
        for(int x : A)
            rst = x + rst;
        return rst.charAt(0) == '0' ? "0" : rst;
    }
   
    public static class Comp implements Comparator<Integer>{
        public int compare(Integer a, Integer b){
            String sa = String.valueOf(a);
            String sb = String.valueOf(b);
            return (sa+sb).compareTo(sb+sa);
        }
    }



Repeated DNA Sequences
public List<String> findRepeatedDnaSequences(String s) {
        List<String> list = new ArrayList<String>();
        if(s == null || s.length() <= 10)
            return list;
       
        Map<String, Integer> map = new HashMap<String, Integer>();
       
        for(int i=0; i<s.length()-9; ++i){
            String seq = s.substring(i, i+10);
            if(!map.containsKey(seq)){
                map.put(seq, 1);
                continue;
            }
            if(map.get(seq) == 1){
                list.add(seq);
                map.put(seq, 2);
            }
        }
       
        return list;
    }


Binary Tree Right Side View
public List<Integer> rightSideView(TreeNode root) {
        List<Integer> rst = new ArrayList<Integer>();
        if(root == null)
            return rst;
       
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        queue.offer(root);
        int num = 1;
        while(!queue.isEmpty()){
            int count = 0;
            rst.add(queue.peek().val);
            for(int i=0; i<num; ++i){
                TreeNode node = queue.poll();
                if(node.right != null){
                    queue.offer(node.right);
                    ++count;
                }
                if(node.left != null){
                    queue.offer(node.left);
                    ++count;
                }
            }
            num = count;
        }
       
        return rst;
    }


Number of Islands
public int numIslands(char[][] grid) {
        if(grid == null || grid.length == 0 || grid[0].length == 0)
            return 0;
       
        int count = 1;
        for(int i=0; i<grid.length; ++i)
            for(int j=0; j<grid[0].length; ++j)
                if(grid[i][j] == '1')
                    color(grid, i, j, ++count);
        return count-1;
    }
   
    private void color(char[][] grid, int r, int c, int cl){
        if(r < 0 || r >= grid.length)
            return;
        if(c < 0 || c >= grid[0].length)
            return;
        if(grid[r][c] != '1')
            return;
        grid[r][c] = (char)(cl+'0');
        color(grid, r-1, c, cl);
        color(grid, r+1, c, cl);
        color(grid, r, c-1, cl);
        color(grid, r, c+1, cl);
    }


Bitwise AND of Numbers Range
public int rangeBitwiseAnd(int m, int n) {
        int rst = 0;
        int d = 0;
        while(m > 0){
            if(n == m)
                rst += (m&1)<<d;
            m >>= 1;
            n >>= 1;
            ++d;
        }
        return rst;
    }


Course Schedule
public boolean canFinish(int numCourses, int[][] prerequisites) {
        Map<Integer, List<Integer>> nodes = new HashMap<Integer, List<Integer>>();
        for(int i=0; i<numCourses; ++i)
            nodes.put(i, new ArrayList<Integer>());
       
        for(int i=0; i<prerequisites.length; ++i)
            nodes.get(prerequisites[i][0]).add(prerequisites[i][1]);
       
        Set<Integer> visited = new HashSet<Integer>();
        Set<Integer> valid = new HashSet<Integer>();
        for(int i=0; i<numCourses; ++i){
            visited.add(i);
            if(!check(i, visited, valid, nodes))
                return false;
            valid.add(i);
            visited.remove(i);
        }
       
        return true;
    }
   
    private boolean check(int id, Set<Integer> visited, Set<Integer> valid, Map<Integer, List<Integer>> nodes){
        if(valid.contains(id))
            return true;
        for(int next : nodes.get(id)){
            if(visited.contains(next))
                return false;
            visited.add(next);
            if(!check(next, visited, valid, nodes))
                return false;
            valid.add(next);
            visited.remove(next);
        }
        return true;
    }


Minimum Size Subarray Sum
positive array
public int minSubArrayLen(int s, int[] nums) {
        if(nums.length == 0)
            return 0;
        int len = 0;
        int left = 0;
        int right = 0;
        int sum = nums[0];
        while(right < nums.length){
            if(sum >= s){
                len = len == 0 ? right-left+1 : Math.min(len, right-left+1);
                sum -= nums[left++];
                continue;
            }
            if(right < nums.length-1)
                sum += nums[++right];
            else
                break;
        }
        return len;
    }



House Robber
public int rob(int[] nums) {
        if(nums.length == 0)
            return 0;
        int[] dp = new int[nums.length+1];
        dp[1] = nums[0];
       
        for(int i=2; i<dp.length; ++i){
            dp[i] = Math.max(dp[i-1], dp[i-2] + nums[i-1]);
        }
       
        return dp[nums.length];
    }


Kth Largest Element in an Array
public int findKthLargest(int[] nums, int k) {
        PriorityQueue<Integer> q = new PriorityQueue<Integer>();
        for(int x : nums){
            if(q.size() < k){
                q.offer(x);
                continue;
            }
            if(x > q.peek()){
                q.poll();
                q.offer(x);
            }
        }
        return q.peek();
    }
QuickSort Partition O(n)



Combination Sum III
public List<List<Integer>> combinationSum3(int k, int n) {
        List<List<Integer>> rst = new ArrayList<List<Integer>>();
        if(k <= 0 || n <= 0)
            return rst;
        Set<Integer> set = new HashSet<Integer>();
        dfs(rst, new ArrayList<Integer>(), set, 1, k, n);
        return rst;
    }
<pre name="code" class="java">private void dfs(List<List<Integer>> rst, List<Integer> list, Set<Integer> set, int s, int k, int n){
        if(k == 0 && n == 0){
            rst.add(new ArrayList<Integer>(list));
            return;
        }
        if(k == 0 || n <= 0)
            return;
       
        for(int i=s; i<=9; ++i){
            if(!set.contains(i)){
                list.add(i);
                set.add(i);
                dfs(rst, list, set, i+1, k-1, n-i);
                set.remove(i);
                list.remove(list.size()-1);
            }
        }
       
    }


 

Contains Duplicate II
public boolean containsNearbyDuplicate(int[] nums, int k) {
        if(nums == null || nums.length < 2)
            return false;
           
        Map<Integer, Integer> map = new HashMap<Integer, Integer>();
        for(int i=0; i<nums.length; ++i){
            if(map.containsKey(nums[i]) && i-map.get(nums[i]) <= k)
                return true;
            map.put(nums[i], i);
        }
        return false;
    }


Valid Anagram
public boolean isAnagram(String s, String t) {
        char[] sch = s.toCharArray();
        char[] tch = t.toCharArray();
        Arrays.sort(sch);
        Arrays.sort(tch);
        String ns = String.valueOf(sch);
        String nt = String.valueOf(tch);
        return ns.equals(nt);
    }



Kth Smallest Element in a BST
int rst;
    public int kthSmallest(TreeNode root, int k) {
        inorder(root, k);
        return rst;
    }
   
    private int inorder(TreeNode root, int k){
        if(root == null)
            return 0;
        int num = inorder(root.left, k);
        if(num >= k)
            return k+1;
        num++;
        if(num == k){
            rst = root.val;
            return num;
        }
        return num + inorder(root.right, k-num);
    }

Follow up:
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?
  1. Try to utilize the property of a BST.
  2. What if you could modify the BST node's structure?
  3. The optimal runtime complexity is O(height of BST).
每个树节点可以设一个值:其下所有节点数

House Robber II
public int rob(int[] nums) {
        if(nums == null || nums.length == 0)
            return 0;
        if(nums.length == 1)
            return nums[0];
        if(nums.length == 2)
            return Math.max(nums[0], nums[1]);
       
        int[] dp = new int[nums.length];
        dp[0] = nums[0];
        dp[1] = Math.max(nums[0], nums[1]);
        for(int i=2; i<nums.length-1; ++i)
            dp[i] = Math.max(dp[i-1], nums[i] + dp[i-2]);
       
        int rst = dp[nums.length-2];
       
        if(nums.length == 3)
            return Math.max(rst, nums[2]);
           
        dp[1] = nums[1];
        dp[2] = Math.max(nums[1], nums[2]);
        for(int i=3; i<nums.length; ++i)
            dp[i] = Math.max(dp[i-1], nums[i] + dp[i-2]);
           
        return Math.max(rst, dp[nums.length-1]);
    }


Fraction to Recurring Decimal
public String fractionToDecimal(int numerator, int denominator) {
        if (numerator == 0) return "0";
        if (denominator == 0) return "";
         
        String ans = "";
         
        //如果结果为负数
        if ((numerator < 0) ^ (denominator < 0)) {
            ans += "-";
        }
         
        //下面要把两个数都转为正数,为避免溢出,int转为long
        long num = numerator, den = denominator;
        num = Math.abs(num);
        den = Math.abs(den);
         
        //结果的整数部分
        long res = num / den;
        ans += String.valueOf(res);
         
        //如果能够整除,返回结果
        long rem = (num % den) * 10;
        if (rem == 0) return ans;
         
        //结果的小数部分
        HashMap<Long, Integer> map = new HashMap<Long, Integer>();
        ans += ".";
        while (rem != 0) {
            //如果前面已经出现过该余数,那么将会开始循环
            if (map.containsKey(rem)) {
                int beg = map.get(rem); //循环体开始的位置
                String part1 = ans.substring(0, beg);
                String part2 = ans.substring(beg, ans.length());
                ans = part1 + "(" + part2 + ")";
                return ans;
            }
             
            //继续往下除
            map.put(rem, ans.length());
            res = rem / den;
            ans += String.valueOf(res);
            rem = (rem % den) * 10;
        }
         
        return ans;
    }


Majority Element II
public List<Integer> majorityElement(int[] nums) {
        List<Integer> rst = new ArrayList<Integer>();
        if(nums == null || nums.length == 0)
            return rst;
        if(nums.length < 2){
            rst.add(nums[0]);
            return rst;
        }
       
        int a = nums[0];
        int b = 0;
        int ac = 1;
        int bc = 0;
       
        for(int i=1; i<nums.length; ++i){
            if(nums[i] == a){
                ac++;
            }
            else if(nums[i] == b){
                bc++;
            }
            else if(ac == 0){
                ac = 1;
                a = nums[i];
            }
            else if(bc == 0){
                bc = 1;
                b = nums[i];
            }
            else{
                bc--;
                ac--;
            }
        }
       
// 最多两个  但不保证有两个

        ac = 0;
        bc = 0;
        for(int i=0; i<nums.length; ++i){
            if(nums[i] == a)
                ac++;
            else if(nums[i] == b)
                bc++;
        }
       
        if(ac > nums.length/3)
            rst.add(a);
        if(bc > nums.length/3)
            rst.add(b);
       
        return rst;
    }



Reverse Bits
public int reverseBits(int n) {
        int rst = 0;
        for(int i=0; i<32; ++i){
            rst += (n >> i & 1) << 31-i;
        }
        return rst;
    }


Happy Number
public boolean isHappy(int n) {
        Set<Integer> set = new HashSet<Integer>();
        while(n != 1){
            if(set.contains(n))
                return false;
            set.add(n);
            int m = 0;
            while(n > 0){
                int d = n%10;
                m += d*d;
                n /= 10;
            }
            n = m;
        }
        return true;
    }


Reverse Linked List
public ListNode reverseList(ListNode head) {
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        while(head != null && head.next != null){
            ListNode node = head.next;
            head.next = node.next;
            node.next = dummy.next;
            dummy.next = node;
        }
        return dummy.next;
    }

// without dummy
public ListNode reverseList(ListNode head) {
        if(head == null || head.next == null)
            return head;
       
        ListNode left = head;
        ListNode right = head;
       
        while(right.next != null){
            ListNode node = right.next;
            right.next = right.next.next;
            node.next = left;
            left = node;
        }
       
        return left;
    }


Number of 1 Bits
public int hammingWeight(int n) {
        int count = 0;
        for(int i=0; i<32; ++i){
            count += n >> i & 1;
        }
       
        return count;
    }



Best Time to Buy and Sell Stock IV
locale[i][j] ith day involved in the jth transaction.
global[i][j] ith day may be not involved in the jth transaction. it is the global max value.

public int maxProfit(int k, int[] prices) {
        if(prices.length <= 1 || k <= 0)
            return 0;
       
       // if (k == 1000000000)
       // return 1648961;
 
        int[][] local = new int[prices.length][k+1];
        int[][] global = new int[prices.length][k+1];
       
        for(int j=1; j<=k; ++j)
            for(int i=1; i<prices.length; ++i){
                int diff = prices[i] - prices[i-1];
                local[i][j] = Math.max(global[i-1][j-1] + Math.max(diff, 0), local[i-1][j] + diff);
                global[i][j] = Math.max(global[i-1][j], local[i][j]);
            }
       
        return global[prices.length-1][k];
    }


Rotate Array
public void rotate(int[] nums, int k) {
        k %= nums.length;
        if(k <= 0)
            return;
           
        int left = 0;
        int right = nums.length-k-1;
        while(left < right){
            swap(nums, left++, right--);
        }
        left = nums.length-k;
        right = nums.length-1;
        while(left < right){
            swap(nums, left++, right--);
        }
        left = 0;
        right = nums.length-1;
        while(left < right){
            swap(nums, left++, right--);
        }
    }
   
    private void swap(int[] nums, int i, int j){
        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    }


Remove Linked List Elements
public ListNode removeElements(ListNode head, int val) {
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode curr = dummy;
       
        while(curr.next != null){
            if(curr.next.val == val)
                curr.next = curr.next.next;
            else
                curr = curr.next;
        }
       
        return dummy.next;
    }


Count Primes
public int countPrimes(int n) {
        boolean[] isPrime = new boolean[n];
        for (int i = 2; i < n; i++)
            isPrime[i] = true;
       
        for(int i=2; i*i<n; ++i){
            if(!isPrime[i])
                continue;
            for(int j=i*i; j<n; j+=i)
                isPrime[j] = false;
        }
       
        int count = 0;
        for(int i=2; i<n; ++i)
            if(isPrime[i])
                ++count;
       
        return count;
    }


// my solution
public int countPrimes(int n) {
        List<Integer> primes = new ArrayList<Integer>();
       
        for(int i=2; i<n; ++i){
            boolean isprime = true;
            for(int x : primes){
                if(x*x > i)
                    break;
                if(i%x == 0){
                    isprime = false;
                    break;
                }
            }
            if(isprime){
                primes.add(i);
            }
        }
       
        return primes.size();
    }


Isomorphic Strings
public boolean isIsomorphic(String s, String t) {
        if(s.length() != t.length())
            return false;
       
        Map<Character, Character> map = new HashMap<Character, Character>();
       
        for(int i=0; i<s.length(); ++i){
            char key = s.charAt(i);
            char val = t.charAt(i);
            if(map.containsKey(key)){
                if(map.get(key) != val)
                    return false;
            }
            else{
                if(map.containsValue(val))
                    return false;
                map.put(key, val);
            }
        }
        return true;
    }



Implement Trie (Prefix Tree)
class TrieNode {
    // Initialize your data structure here.
    public boolean isLeaf;
    public Map<Character, TrieNode> children;
    public TrieNode() {
        children = new HashMap<Character, TrieNode> ();
    }
}

public class Trie {
    private TrieNode root;

    public Trie() {
        root = new TrieNode();
    }

    // Inserts a word into the trie.
    public void insert(String word) {
        if(word == null || word.length() == 0)
            return;
        TrieNode node = root;
        for(int i=0; i<word.length(); ++i){
            char ch = word.charAt(i);
            if(node.children.get(ch) == null)
                node.children.put(ch, new TrieNode());
            node = node.children.get(ch);
        }
        node.isLeaf = true;
    }

    // Returns if the word is in the trie.
    public boolean search(String word) {
        TrieNode node = searchNode(word);
        if(node == null || !node.isLeaf)
            return false;
        return true;
    }

    // Returns if there is any word in the trie
    // that starts with the given prefix.
    public boolean startsWith(String prefix) {
        TrieNode node = searchNode(prefix);
        return node != null;
    }
   
    private TrieNode searchNode(String str){
        if(str == null || str.length() == 0)
            return null;
        TrieNode node = root;
        for(int i=0; i<str.length(); ++i){
            if(node.children.get(str.charAt(i)) == null)
                return null;
            node = node.children.get(str.charAt(i));
        }
        return node;
    }
   
}


Course Schedule II
public int[] findOrder(int numCourses, int[][] prerequisites) {
        Map<Integer, Set<Integer>> map = new HashMap<Integer, Set<Integer>>();
        Map<Integer, Set<Integer>> connect = new HashMap<Integer, Set<Integer>>();
        for(int i=0; i<numCourses; ++i){
            map.put(i, new HashSet<Integer>());
            connect.put(i, new HashSet<Integer>());
        }
           
        for(int i=0; i<prerequisites.length; ++i){
            map.get(prerequisites[i][0]).add(prerequisites[i][1]);
            connect.get(prerequisites[i][1]).add(prerequisites[i][0]);
        }
       
        Queue<Integer> q = new LinkedList<Integer>();
        for(int i=0; i<numCourses; ++i)
            if(map.get(i).isEmpty())
                q.offer(i);
       
        int[] rst = new int[numCourses];
        int count = 0;
        while(!q.isEmpty()){
            int course = q.poll();
            rst[count++] = course;
            for(int x : connect.get(course)){
                map.get(x).remove(course);
                if(map.get(x).isEmpty())
                    q.offer(x);
            }
        }
        if(count < numCourses-1)
            return new int[0];
        return rst;
    }



Add and Search Word - Data structure design
public class WordDictionary {
   
    private class Node{
        public boolean isleaf;
        public Map<Character, Node> children;
        public Node(){
            children = new HashMap<Character, Node>();
        }
    }
   
    private Node root = new Node();

    // Adds a word into the data structure.
    public void addWord(String word) {
        if(word == null || word.length() == 0)
            return;
        Node node = root;
        for(int i=0; i<word.length(); ++i){
            char ch = word.charAt(i);
            if(node.children.get(ch) == null)
                node.children.put(ch, new Node());
            node = node.children.get(ch);
        }
        node.isleaf = true;
    }

    // Returns if the word is in the data structure. A word could
    // contain the dot character '.' to represent any one letter.
    public boolean search(String word) {
        if(word == null || word.length() == 0)
            return false;
        return search(root, word, 0);
    }
   
    private boolean search(Node node, String word, int k){
       
        if(k == word.length()){
            return node != null && node.isleaf;
        }
       
        char ch = word.charAt(k);
        if(ch != '.'){
            if(node.children.get(ch) == null)
                return false;
            return search(node.children.get(ch), word, k+1);
        }
        else{
            for(Node child : node.children.values()){
                if(search(child, word, k+1))
                    return true;
            }
            return false;
        }
    }
}


Contains Duplicate
public boolean containsDuplicate(int[] nums) {
        if(nums == null || nums.length <= 1)
            return false;
        Set<Integer> set = new HashSet<Integer>();
        for(int x : nums){
            if(set.contains(x))
                return true;
            set.add(x);
        }
       
        return false;
    }


Different Ways to Add Parentheses
public List<Integer> diffWaysToCompute(String input) {
        List<Integer> rst = new ArrayList<Integer>();
        if(input == null || input.length() == 0)
            return rst;
       
        boolean op = false;
        for(int i=1; i<input.length(); ++i){
            char ch = input.charAt(i);
            if(ch == '-'){
                List<Integer> left = diffWaysToCompute(input.substring(0, i));
                List<Integer> right = diffWaysToCompute(input.substring(i+1, input.length()));
                for(int x : left)
                    for(int y : right)
                        rst.add(x - y);
                op = true;
            }
            else if(ch == '+'){
                List<Integer> left = diffWaysToCompute(input.substring(0, i));
                List<Integer> right = diffWaysToCompute(input.substring(i+1, input.length()));
                for(int x : left)
                    for(int y : right)
                        rst.add(x + y);
                op = true;
            }
            else if(ch == '*'){
                List<Integer> left = diffWaysToCompute(input.substring(0, i));
                List<Integer> right = diffWaysToCompute(input.substring(i+1, input.length()));
                for(int x : left)
                    for(int y : right)
                        rst.add(x * y);
                op = true;
            }
        }
        if(!op){
            rst.add(Integer.parseInt(input));
        }
        return rst;
    }



Maximal Square
public int maximalSquare(char[][] matrix) {
        if(matrix == null)
            throw new IllegalArgumentException();
        if(matrix.length == 0 || matrix[0].length == 0)
            return 0;
       
        int m = matrix.length;
        int n = matrix[0].length;
        int[][] dp = new int[m][n];
        int max = 0;
       
        for(int i=0; i<m; ++i){
            dp[i][0] = matrix[i][0] - '0';
            max = Math.max(max, dp[i][0]);
        }
        for(int i=0; i<n; ++i){
            dp[0][i] = matrix[0][i] - '0';
            max = Math.max(max, dp[0][i]);
        }
       
        for(int i=1; i<m; ++i)
            for(int j=1; j<n; ++j){
                if(matrix[i][j] == '1'){
                    dp[i][j] = Math.min(dp[i-1][j], Math.min(dp[i-1][j-1], dp[i][j-1])) + 1;
                    max = Math.max(max, dp[i][j]);
                }
            }
       
        return max*max;
    }


Merge Intervals
public List<Interval> merge(List<Interval> intervals) {
        Collections.sort(intervals, new Comp());
       
        List<Interval> rst = new ArrayList<Interval>();
        if(intervals == null || intervals.size() == 0)
            return intervals;
       
        Interval inter = null;
        for(Interval it : intervals){
            if(inter == null){
                inter = it;
                continue;
            }
            if(inter.end >= it.start){
                inter.end = Math.max(inter.end, it.end);
                continue;
            }
            rst.add(inter);
            inter = it;
        }
        rst.add(inter);
       
        return rst;
    }
   
    private static class Comp implements Comparator<Interval>{
        public int compare(Interval inter1, Interval inter2){
            return inter1.start - inter2.start;
        }
    }



Binary Tree Paths
public List<String> binaryTreePaths(TreeNode root) {
        List<String> rst = new ArrayList<String>();
        dfs(rst, new ArrayList<Integer>(), root);
        return rst;
    }
   
    private void dfs(List<String> rst, List<Integer> list, TreeNode node){
        if(node == null)
            return;
       
        list.add(node.val);
        if(node.left == null && node.right == null){
            String str = "" + list.get(0);
            for(int i=1; i<list.size(); ++i)
                str += "->" + list.get(i);
            rst.add(str);
        }
        else{
            dfs(rst, list, node.left);
            dfs(rst, list, node.right);
        }
        list.remove(list.size()-1);
    }


Word Pattern
public boolean wordPattern(String pattern, String str) {
        String[] strs = str.split(" ");
        Map<Character, String> map = new HashMap<Character, String>();
        int index = 0;
        for(int i=0; i<strs.length; ++i){
            if(strs[i].length() == 0)
                continue;
            if(index >= pattern.length())
                return false;
            char ch = pattern.charAt(index++);
            if(map.containsKey(ch)){
                if(!map.get(ch).equals(strs[i]))
                    return false;
                continue;
            }
            if(map.containsValue(strs[i]))
                return false;
            map.put(ch, strs[i]);
        }
        return index == pattern.length();
    }


Minimum Window Substring
public String minWindow(String s, String t) {
        if(s == null || t == null)
            throw new IllegalArgumentException();
        if(s.length() == 0 || t.length() == 0)
            return "";
       
        Map<Character, Integer> map = new HashMap<Character, Integer>();
        int count = 0;
        for(int i=0; i<t.length(); ++i){
            char key = t.charAt(i);
            if(map.containsKey(key))
                map.put(key, map.get(key)+1);
            else{
                map.put(key, 1);
                ++count;
            }
        }
       
        int left = 0;
        int right = 0;
        int len = s.length()+1;
        String str = "";
        while(right < s.length()){
            char ch = s.charAt(right);
            if(map.containsKey(ch)){
                map.put(ch, map.get(ch)-1);
                if(map.get(ch) == 0)
                    --count;
                if(count == 0){
                    if(right-left+1 < len){
                        str = s.substring(left, right+1);
                        len = right-left+1;
                    }
                    while(left < right){
                        char key = s.charAt(left++);
                        if(map.containsKey(key)){
                            map.put(key, map.get(key)+1);
                            if(map.get(key) == 1){
                                ++count;
                                break;
                            }
                        }
                        if(right-left+1 < len){
                            str = s.substring(left, right+1);
                            len = right-left+1;
                        }
                    }
                }
            }
            ++right;
        }
       
        return str;
    }


Lowest Common Ancestor of a Binary Search Tree
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root == null)
            return null;
        int min = Math.min(q.val, p.val);
        int max = Math.max(q.val, p.val);
       
        if(root.val == min || root.val == max || root.val > min && root.val < max)
            return root;
       
        if(root.val < min)
            return lowestCommonAncestor(root.right, p, q);
        else
            return lowestCommonAncestor(root.left, p, q);
    }



Lowest Common Ancestor of a Binary Tree
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root == null)
            return null;
        if(root == p || root == q)
            return root;
       
        TreeNode left = lowestCommonAncestor(root.left, p, q);
        TreeNode right = lowestCommonAncestor(root.right, p, q);
       
        if(left == null && right == null)
            return null;
        if(left != null && right != null)
            return root;
        return left != null ? left : right;
    }


H-Index
public int hIndex(int[] citations) {
        int[] counts = new int[citations.length+1];
       
        for(int num : citations)
            if(num > citations.length)
                counts[citations.length]++;
            else
                counts[num]++;
       
        int sum = 0;
        for(int i=counts.length-1; i>0; --i){
            int count = sum + counts[i];
            if(count >= i)
                return i;
            sum = count;
        }
        return 0;
    }



H-Index II
O(logn)
public int hIndex(int[] citations) {
        int left = 0;
        int right = citations.length-1;
        int total = citations.length;
        int hindex = 0;
       
        while(left <= right){
            int mid = left + (right-left)/2;
            if(citations[mid] >= total - mid){
                hindex = Math.max(hindex, total - mid);
                right = mid-1;
            }
            else
                left = mid+1;
        }
       
        return hindex;
    }



Sliding Window Maximum
public int[] maxSlidingWindow(int[] nums, int k) {
        if(k > nums.length)
            throw new IllegalArgumentException();
        if(nums.length == 0)
            return nums;
           
        int[] rst = new int[nums.length-k+1];
        Deque<Integer> deq = new ArrayDeque<Integer>();
       
        int index = 0;
        for(int i=0; i<nums.length; ++i){
            if(!deq.isEmpty() && i-deq.getFirst() == k)
                deq.removeFirst();
            while(!deq.isEmpty() && nums[deq.getLast()] < nums[i])
                deq.removeLast();
            deq.addLast(i);
            if(i >= k-1)
                rst[index++] = nums[deq.getFirst()];
        }
       
        return rst;
    }















  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值