LeetCode 全解(bug free 训练)

1.Two Sum

Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.

使用hash

public int[] twoSum(int[] nums, int target) {
        int[] res = new int[2];
        if (nums == null || nums.length < 2) {
            return res;
        }
        HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
        int n = nums.length;
        for (int i = 0; i < n; i++) {
            if (map.containsKey(target - nums[i])) {
                res[0] = map.get(target - nums[i]);
                res[1] = i;
                return res;
            }
            map.put(nums[i], i);
        }
        return res;
    }
View Code

2.Add Two Numbers

You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.
You may assume the two numbers do not contain any leading zero, except the number 0 itself.
Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8

dummyHead cur控制。carry携带进位

def addTwoNumbers(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        dummyHead = ListNode(0)
        cur = dummyHead
        carry = 0
        while (l1 or l2):
            sum = 0
            if l1:
                sum += l1.val
                l1 = l1.next
            if l2:
                sum += l2.val
                l2 = l2.next
            sum += carry
            carry = sum / 10
            cur.next = ListNode(sum % 10)
            cur = cur.next
        if carry != 0:
            cur.next = ListNode(carry)
        return dummyHead.next
View Code

3.Longest Substring Without Repeating Characters --- not bug free

Given a string, find the length of the longest substring without repeating characters.

Examples:

Given "abcabcbb", the answer is "abc", which the length is 3.

Given "bbbbb", the answer is "b", with the length of 1.

Given "pwwkew", the answer is "wke", with the length of 3. Note that the answer must be a substring, "pwke" is a subsequence and not a substring.

使用数组充当map

注意:left的更新规则,可能有些出现过的点上次出现的位置还在left的左边。最后也需要一个max的操作

 1 public int lengthOfLongestSubstring(String s) {
 2         if (s == null || s.length() == 0) {
 3             return 0;
 4         }
 5         int[] map = new int[128];
 6         Arrays.fill(map, -1);
 7         char[] chars = s.toCharArray();
 8         int n = s.length();
 9         int left = 0;
10         int right = 0;
11         int res = 0;
12         while (right < n) {
13             if (map[chars[right]] == -1) {
14                 map[chars[right]] = right;
15                 right++;
16             } else {
17                 res = Math.max(res, right - left); 
18                 left = Math.max(left, map[chars[right]] + 1); // Attention!
19                 map[chars[right]] = right;
20                 right++;
21             }
22         }
23         res = Math.max(res, right - left);
24         return res; // Attention!
25     }
View Code

4.Median of Two Sorted Arrays

There are two sorted arrays nums1 and nums2 of size m and n respectively.

Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).

findTopK。检测四个条件:是否一个为空了,是否找第一个,是否其中一个不够 k / 2 了,谁大谁小。

public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        if (nums1 == null || nums2 == null) {
            return 0.0;
        }
        int m = nums1.length;
        int n = nums2.length;
        int total = m + n;
        if (total % 2 == 0) {
            return (findTopK(nums1, 0, m - 1, nums2, 0, n - 1, total / 2) 
                + findTopK(nums1, 0, m - 1, nums2, 0, n - 1, total / 2 + 1)) / 2.0;
        } else {
            return (double)findTopK(nums1, 0, m -1, nums2, 0, n - 1, total / 2 + 1);
        }
    }
    public int findTopK(int[] nums1, int start1, int end1, int[] nums2, int start2, int end2, int k) {
        if (start1 > end1) {
            return nums2[start2 + k - 1];
        }
        if (start2 > end2) {
            return nums1[start1 + k - 1];
        }
        if (k == 1) {
            return Math.min(nums1[start1], nums2[start2]);
        }
        if (start1 + k / 2 - 1 > end1) {
            return findTopK(nums1, start1, end1, nums2, start2 + k / 2, end2, k - k / 2);
        }
        if (start2 + k / 2 - 1 > end2) {
            return findTopK(nums1, start1 + k / 2, end1, nums2, start2, end2, k - k / 2);
        }
        if (nums1[start1 + k / 2 - 1] > nums2[start2 + k / 2 - 1]) {
             return findTopK(nums1, start1, end1, nums2, start2 + k / 2, end2, k - k / 2);
        } else {
            return findTopK(nums1, start1 + k / 2, end1, nums2, start2, end2, k - k / 2);
        }
    }
View Code

5.Longest Palindromic Substring

Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.

以每个点为中心扩张

global low
    global res
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        global low
        global res
        low = 0
        res = 1
        if not s:
            return s
        n = len(s)
        for i in range(n - 1):
            self.test(s, i, i)
            self.test(s, i, i + 1)
        return s[low : low + res]
    def test(self, s, i, j):
        n = len(s)
        global res
        global low
        while (i >= 0 and j < n and s[i] == s[j]):
            i -= 1
            j += 1
        if (j - i - 1 > res):
            res = j - i - 1
            low = i + 1
View Code

dp dp[i][j]表示[i, j]子串是不是回文串。全局记录一个最大最小

def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        if not s:
            return s
        n = len(s)
        start = 0
        end = 0
        dp = [[False for col in range(n)] for row in range(n)] # dp[i][j]表示[i, j]是否是回文串
        for i in range(n):
            dp[i][i] = True
        for k in range(1, n):
            for i in range(n - k):
                j = i + k
                if (s[i] == s[j] and (k == 1 or dp[i + 1][j - 1])):
                    dp[i][j] = True
                    if (end - start < k) :
                        start = i
                        end = j
        return s[start : end + 1]
View Code

6.ZigZag Conversion

The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)
P   A   H   N
A P L S I I G
Y   I   R
And then read line by line: "PAHNAPLSIIGYIR"
Write the code that will take a string and make this conversion given a number of rows:
string convert(string text, int nRows);
convert("PAYPALISHIRING", 3) should return "PAHNAPLSIIGYIR".

每一行用一个StringBuilder 来记录

public String convert(String s, int numRows) {
        if (s == null || s.length() <= numRows || numRows == 1) {
            return s;
        }
        StringBuilder[] sb = new StringBuilder[numRows];
        for (int j = 0; j < numRows; j++) {
            sb[j] = new StringBuilder();
        }
        char[] chars = s.toCharArray();
        int n = s.length();
        int i = 0;
        while (i < n) {
            for (int j = 0; j < numRows && i < n; j++) {
                sb[j].append(chars[i++]);
            }
            for (int j = numRows - 2; j > 0 && i < n; j--) {
                sb[j].append(chars[i++]);
            }
        }
        for (int j = 1; j < numRows; j++) {
            sb[0].append(sb[j]);
        }
        return sb[0].toString();
    }
View Code

7.Reverse Integer

Reverse digits of an integer.

Example1: x = 123, return 321
Example2: x = -123, return -321

直接使用负数来计算也是可以的。注意越界单独处理就可以了。

public int reverse(int x) {
        long res = 0;
        while (x != 0) {
            int temp = x % 10;
            res = res * 10 + temp;
            if (res > Integer.MAX_VALUE || res < Integer.MIN_VALUE) {
                return 0;
            }
            x /= 10;
        }
        return (int)res;
    }
View Code

8.String to Integer (atoi)

首位空格,非数字,越界, 正负号

public int myAtoi(String str) {
        if (str == null) {
            return 0;
        }
        str = str.trim();
        if (str.length() == 0) {
            return 0;
        }
        char[] chars = str.toCharArray();
        long res = 0;
        int start = 0;
        boolean flag = false;
        if (chars[0] == '-') {
            flag = true;
            start = 1;
        }
        if (chars[0] == '+') {
            start = 1;
        }
        int n = str.length();
        while (start < n) {
            if (Character.isDigit(chars[start])) {
                res = 10 * res + chars[start++] - '0';
                if (res > Integer.MAX_VALUE) {
                    break;
                }
            } else {
                break;
            }
        }
        if (flag) {
            res = -res;
        }
        if (res > Integer.MAX_VALUE) {
            return Integer.MAX_VALUE;
        }
        if (res < Integer.MIN_VALUE) {
            return Integer.MIN_VALUE;
        }
        return (int)res;
    }
View Code

9.Palindrome Number

Determine whether an integer is a palindrome. Do this without extra space.

reverse之后看看等不等就可以了

public boolean isPalindrome(int x) {
        if (x < 0) {
            return false;
        }
        long reverse = 0;
        int temp = x;
        while (temp != 0) {
            reverse = reverse * 10 + temp % 10;
            temp = temp / 10;
        }
        return (int)reverse == x;
    }
View Code

10.Regular Expression Matching

Implement regular expression matching with support for '.' and '*'.

'.' Matches any single character.
'*' Matches zero or more of the preceding element.

The matching should cover the entire input string (not partial).

The function prototype should be:
bool isMatch(const char *s, const char *p)

Some examples:
isMatch("aa","a") → false
isMatch("aa","aa") → true
isMatch("aaa","aa") → false
isMatch("aa", "a*") → true
isMatch("aa", ".*") → true
isMatch("ab", ".*") → true
isMatch("aab", "c*a*b") → true

*可以把前边的字符也拿走。

dp[i][j]表示s的前i个字符是否能够与p的前j个字符匹配。

首先初始化s取0个,p的话如果遇到*,就把之前的一个拿走a*b*c*,这样可能匹配。

然后如果遇到字符相等或p遇到'.',那简单。

如果p遇到'*',那么就考虑代表0个1个多个。注意如果p的*的前一个不等于s的当前 ,也不为'.'。那么就是能拿走,代表0个。不然一起处理会带来“*”代表的不是之前字符的问题。

public boolean isMatch(String s, String p) {
        if (s == null || p == null) {
            return false;
        }
        int m = s.length();
        int n = p.length();
        char[] sChars = s.toCharArray();
        char[] pChars = p.toCharArray();
        boolean[][] dp = new boolean[m + 1][n + 1]; // dp[i][j] 表示 s 的前 i 个字符和 p 的前 j 个字符是否能够匹配
        dp[0][0] = true;
        if (n != 0 && pChars[0] == '*') {
            return false;
        }
        for (int j = 2; j <= n; j++) {
            if (pChars[j - 1] == '*') {
                dp[0][j] = dp[0][j - 2];
            }
        }
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                if (sChars[i - 1] == pChars[j - 1] || pChars[j - 1] == '.') {
                    dp[i][j] = dp[i - 1][j - 1];
                } else if (pChars[j - 1] == '*') {
                    if (pChars[j - 2] == sChars[i - 1] || pChars[j - 2] == '.') {
                        dp[i][j] = dp[i][j - 1] || dp[i][j - 2] || dp[i - 1][j];
                    } else {
                        dp[i][j] = dp[i][j - 2];
                    }
                }
            }
        }
        return dp[m][n];
    }
View Code

11.Container With Most Water

Given n non-negative integers a1, a2, ..., an, where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water.
Note: You may not slant the container and n is at least 2.

左右两个指针控制移动,哪边小就移动哪边,因为如果移动另一边的话,这边始终会是一个限制。

public int maxArea(int[] height) {
        if (height == null || height.length < 2) {
            return 0;
        }
        int left = 0;
        int right = height.length - 1;
        int res = 0;
        while (left < right) {
            res = Math.max(res, (right - left) * Math.min(height[left], height[right]));
            if (height[left] < height[right]) {
                left++;
            } else {
                right--;
            }
        }
        return res;
    }
View Code

12.Integer to Roman --- not bug free

Given an integer, convert it to a roman numeral.
Input is guaranteed to be within the range from 1 to 3999.

变换点为1 4 5 9 10 40 50 90 100...所以特别标注出这些点来,其他的就是累加

// 罗马数字共有七个,即I(1),V(5),X(10),L(50),C(100),D(500),M(1000)。按照下面的规则可以表示任意正整数。
    // 重复数次:一个罗马数字重复几次,就表示这个数的几倍。 
    // 右加左减:在一个较大的罗马数字的右边记上一个较小的罗马数字,表示大数字加小数字。在一个较大的数字的左边记上一个较小的罗马数字,表示大数字减小数字。但是,左减不能跨越等级。比如,99不可以用IC表示,用XCIX表示。 
    // 加线乘千:在一个罗马数字的上方加上一条横线或者在右下方写M,表示将这个数字乘以1000,即是原数的1000倍。同理,如果上方有两条横线,即是原数的1000000倍。 
    // 单位限制:同样单位只能出现3次,如40不能表示为XXXX,而要表示为XL。
    public String intToRoman(int num) {
        int[] values={1000,900,500,400,100,90,50,40,10,9,5,4,1};
        String[] str={"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < values.length; i++) {
            while (num >= values[i]) {
                sb.append(str[i]);
                num -= values[i];
            }
        }
        return sb.toString();
    }
View Code

13.Roman to Integer --- not bug free

Given a roman numeral, convert it to an integer.
Input is guaranteed to be within the range from 1 to 3999.

从后边开始遍历,以是否大于等于5 50 500 为界

public int romanToInt(String s){
        if(s==null||s.length()==0){
            return 0;
        }
        int len=s.length();
        int res=0;
        for(int i=len-1;i>=0;i--){
            char cur=s.charAt(i);
            
            switch(cur){
                case 'I':
                    res+=res>=5?-1:1;
                    break;
                case 'V':
                    res+=5;
                    break;
                case 'X':
                    res+=res>=50?-10:10;
                    break;
                case 'L':
                    res+=50;
                    break;
                case 'C':
                    res+=res>=500?-100:100;
                    break;
                case 'D':
                    res+=500;
                    break;
                case 'M':
                    res+=1000;
                    break;
            }
        }
        return res;
    }
View Code

14.Longest Common Prefix

Write a function to find the longest common prefix string amongst an array of strings.

先找出最短的,然后长度递减依次检测。

public String longestCommonPrefix(String[] strs) {
        if (strs == null || strs.length == 0) {
            return "";
        }
        int n = strs.length;
        String shortest = strs[0];
        for (String str : strs) {
            if (str.length() < shortest.length()) {
                shortest = str;
            }
        }
        while (shortest.length() > 0) {
            int i = 0;
            for (; i < n; i++) {
                if (strs[i].indexOf(shortest) != 0) {
                    shortest = shortest.substring(0, shortest.length() - 1);
                    break;
                }
            }
            if (i == n) {
                return shortest;
            }
        }
        return "";
    }
View Code

上述方法在一个不满足的时候又重头开始检测,其实没这个必要,只要检测后边的就行了。注意一下

public String longestCommonPrefix(String[] strs) {
        if (strs == null || strs.length == 0) {
            return "";
        }
        String shortest = strs[0];
        int n = strs.length;
        int i = 0;
        while (i < n) {
            while (i < n && strs[i].indexOf(shortest) == 0) {
                i++;
            }
            if (i != n) {
                shortest = shortest.substring(0, shortest.length() - 1);
            }
        }
        return shortest;
    }
View Code

15.3Sum --- not bug free

Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.

排序之后两个指针控制移动。需要注意的是:找到一个满足条件之后,left right 的移动规则,为了避免重复是应该放在一个循环中的。

public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> res = new ArrayList<List<Integer>>();
        if (nums == null || nums.length < 3) {
            return res;
        }
        Arrays.sort(nums);
        int n = nums.length;
        for (int i = 0; i < n; i++) {
            if (i != 0 && nums[i] == nums[i - 1]) {
                continue;
            }
            int left = i + 1;
            int right = n - 1;
            while (left < right) {
                int sum = nums[left] + nums[right] + nums[i];
                if (sum == 0) {
                    List<Integer> cur = new ArrayList<Integer>();
                    cur.add(nums[i]);
                    cur.add(nums[left]);
                    cur.add(nums[right]);
                    res.add(cur);
                    int temp1 = nums[left];
                    int temp2 = nums[right];
                    while (left < right && nums[left] == temp1) {
                        left++;
                    }
                    while (left < right && nums[right] == temp2) {
                        right--;
                    }
                } else if (sum < 0) {
                    left++;
                } else {
                    right--;
                }
            }
        }
        return res;
    }
View Code

16.3Sum Closest

Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.
For example, given array S = {-1 2 1 -4}, and target = 1.
The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).

和上题大同小异

public int threeSumClosest(int[] nums, int target) {
        if (nums == null || nums.length < 3) {
            return Integer.MIN_VALUE;
        }
        Arrays.sort(nums);
        int n = nums.length;
        int res = nums[0] + nums[1] + nums[2];
        for (int i = 0; i < n; i++) {
            if (i != 0 && nums[i] == nums[i - 1]) {
                continue;
            }
            int left = i + 1;
            int right = n - 1;
            while (left < right) {
                int sum = nums[i] + nums[left] + nums[right];
                if (sum == target) {
                    return target;
                } else if (sum < target) {
                    left++;
                    if (Math.abs(res - target) > target - sum) {
                        res = sum;
                    }
                } else {
                    right--;
                    if (Math.abs(res - target) > sum - target) {
                        res = sum;
                    }
                }
            }
        }
        return res;
    }
View Code

17.Letter Combinations of a Phone Number

Given a digit string, return all possible letter combinations that the number could represent.
A mapping of digit to letters (just like on the telephone buttons) is given below.
Input:Digit string "23"
Output: ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].

DFS

public List<String> letterCombinations(String digits) {
        List<String> res = new ArrayList<String>();
        if (digits == null || digits.length() == 0) {
            return res;
        }
        char[][] base = {{},{},{'a', 'b', 'c'},{'d', 'e', 'f'},{'g', 'h', 'i'},{'j', 'k', 'l'},{'m', 'n', 'o'},
                {'p', 'q', 'r', 's'},{'t', 'u', 'v'},{'w', 'x', 'y', 'z'}};
        dfs(digits.toCharArray(), base, res, new char[digits.length()], 0);
        return res;
    }
    public void dfs(char[] chars, char[][] base, List<String> res, char[] strChars, int index) {
        if (index == chars.length) {
            res.add(new String(strChars));
            return;
        }
        for (char c : base[chars[index] - '0']) {
            strChars[index] = c;
            dfs(chars, base, res, strChars, index + 1);
        }
    }
View Code

18.4Sum

Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.

4sum -> 3sum ->2sum

 1 public List<List<Integer>> fourSum(int[] nums, int target) {
 2         List<List<Integer>> res = new ArrayList<List<Integer>>();
 3         if (nums == null || nums.length < 4) {
 4             return res;
 5         }
 6         Arrays.sort(nums);
 7         int n = nums.length;
 8         for (int i = 0; i < n - 3; i++) {
 9             if (i != 0 && nums[i] == nums[i - 1]) {
10                 continue;
11             }
12             List<Integer> cur = new ArrayList<Integer>();
13             cur.add(nums[i]);
14             threeSum(nums, target - nums[i], i + 1, res, cur);
15             cur.remove(cur.size() - 1);
16         }
17         return res;
18     }
19     public void threeSum(int[] nums, int target, int index, List<List<Integer>> res, List<Integer> cur) {
20         int n = nums.length;
21         for (int i = index; i < n - 2; i++) {
22             if (i != index && nums[i] == nums[i - 1]) {
23                 continue;
24             }
25             cur.add(nums[i]);
26             twoSum(nums, target - nums[i], i + 1, res, cur);
27             cur.remove(cur.size() - 1);
28         }
29     }
30     public void twoSum(int[] nums, int target, int index, List<List<Integer>> res, List<Integer> cur) {
31         int n = nums.length;
32         int left = index;
33         int right = n - 1;
34         while (left < right) {
35             int sum = nums[left] + nums[right];
36             if (sum < target) {
37                 left++;
38             } else if (sum > target) {
39                 right--;
40             } else {
41                 cur.add(nums[left]);
42                 cur.add(nums[right]);
43                 res.add(new ArrayList<Integer>(cur));
44                 cur.remove(cur.size() - 1);
45                 cur.remove(cur.size() - 1);
46                 int temp1 = nums[left];
47                 int temp2 = nums[right];
48                 while (left < right && nums[left] == temp1) {
49                     left++;
50                 }
51                 while (left < right && nums[right] == temp2) {
52                     right--;
53                 }
54             }
55         }
56     }
View Code

19. Remove Nth Node From End of List

Given a linked list, remove the nth node from the end of list and return its head.
For example,
   Given linked list: 1->2->3->4->5, and n = 2.
   After removing the second node from the end, the linked list becomes 1->2->3->5.

两个指针控制,找到倒数第n个节点的上一个节点。注意k大于结点总数的处理。

public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummyHead = new ListNode(0);
        dummyHead.next = head;
        ListNode p1 = dummyHead;
        ListNode p2 = dummyHead;
        for (int i = 0; i < n; i++) {
            p1 = p1.next == null ? head : p1.next;
        }
        while (p1.next != null) {
            p1 = p1.next;
            p2 = p2.next;
        }
        p2.next = p2.next.next;
        return dummyHead.next;
    }
View Code

20.Valid Parentheses

Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid.

The brackets must close in the correct order, "()" and "()[]{}" are all valid but "(]" and "([)]" are not.

Stack

 1 public boolean isValid(String s) {
 2         if (s == null || s.length() == 0) {
 3             return false;
 4         }
 5         char[] chars = s.toCharArray();
 6         Stack<Character> stack = new Stack<Character>();
 7         for (char c : chars) {
 8             if (c == '(' || c == '[' || c == '{') {
 9                 stack.push(c);
10             } else {
11                 if (stack.isEmpty()) {
12                     return false;
13                 }
14                 char top = stack.peek();
15                 if (top == '[' && c == ']' || top == '(' && c == ')' || top == '{' && c == '}') {
16                     stack.pop();
17                 } else {
18                     return false;
19                 }
20             }
21         }
22         return stack.isEmpty();
23     }
View Code

21.Merge Two Sorted Lists

Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists.

dummyHead tail, l1 l2往后移动

def mergeTwoLists(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        if not l1:
            return l2
        if not l2:
            return l1
        dummyHead = ListNode(0)
        tail = dummyHead
        while (l1 or l2):
            if (not l1):
                tail.next = l2
                break
            if (not l2):
                tail.next = l1
                break
            if (l1.val < l2.val):
                tail.next = l1
                tail = l1
                l1 = l1.next
            else:
                tail.next = l2
                tail = l2
                l2 = l2.next
        return dummyHead.next
View Code

22.Generate Parentheses

Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.
For example, given n = 3, a solution set is:
[
  "((()))",
  "(()())",
  "(())()",
  "()(())",
  "()()()"
]

dp。dp[i]表示i个括号的组合方式。i个括号组合方式的生成就是在i-1个括号上加一个括号,这个括号内部可以包含0,1,...i-1个括号。

public List<String> generateParenthesis(int n) {
        List<String>[] dp = new ArrayList[n + 1]; // dp[i]表示i个括号的所有可能组合
        dp[0] = new ArrayList<String>();
        dp[0].add("");
        for (int i = 1; i <= n; i++) {
            dp[i] = new ArrayList<String>();
            for (int j = 0; j < i; j++) {
                for (String inner : dp[j]) {
                    StringBuilder sb = new StringBuilder();
                    sb.append("(");
                    sb.append(inner);
                    sb.append(")");
                    int len = sb.length();
                    for (String outter : dp[i - j - 1]) {
                        sb.append(outter);
                        dp[i].add(sb.toString());
                        sb.setLength(len);
                    }
                }
            }
        }
        return dp[n];
    }
View Code

23.Merge k Sorted Lists

Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.

分治。klogn 另外还可以使用优先队列  两两合并

public ListNode mergeKLists(ListNode[] lists) {
        if (lists == null || lists.length == 0) {
            return null;
        }
        return mergeHelper(lists, 0, lists.length - 1);
    }
    public ListNode mergeHelper(ListNode[] lists, int start, int end) {
        if (start == end) {
            return lists[start];
        }
        if (start + 1 == end) {
            return mergeTwo(lists[start], lists[end]);
        }
        int mid = start + (end - start) / 2;
        return mergeTwo(mergeHelper(lists, start, mid), mergeHelper(lists, mid + 1, end));
    }
    public ListNode mergeTwo(ListNode l1, ListNode l2) {
        ListNode dummyHead = new ListNode(0);
        ListNode tail = dummyHead;
        while (l1 != null || l2 != null) {
            if (l1 == null) {
                tail.next = l2;
                break;
            }
            if (l2 == null) {
                tail.next = l1;
                break;
            }
            if (l1.val < l2.val) {
                tail.next = l1;
                tail = l1;
                l1 = l1.next;
            } else {
                tail.next = l2;
                tail = l2;
                l2 = l2.next;
            }
        }
        return dummyHead.next;
    }
View Code

24.Swap Nodes in Pairs

Given a linked list, swap every two adjacent nodes and return its head.

For example,
Given 1->2->3->4, you should return the list as 2->1->4->3.

Your algorithm should use only constant space. You may not modify the values in the list, only nodes itself can be changed.

搞清逻辑就行了。

public ListNode swapPairs(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        ListNode dummyHead = new ListNode(0);
        dummyHead.next = head;
        ListNode tail = dummyHead;
        ListNode cur = head;
        while (cur != null && cur.next != null) {
            ListNode swapNode = cur.next;
            ListNode temp = swapNode.next;
            tail.next = swapNode;
            swapNode.next = cur;
            cur.next = temp;
            tail = cur;
            cur = temp;
        }
        return dummyHead.next;
    }
View Code

25.Reverse Nodes in k-Group --- not bug free

Given a linked list, reverse the nodes of a linked list k at a time and return its modified list.
k is a positive integer and is less than or equal to the length of the linked list. If the number of nodes is not a multiple of k then left-out nodes in the end should remain as it is.
You may not alter the values in the nodes, only nodes itself may be changed.
Only constant memory is allowed.
For example,
Given this linked list: 1->2->3->4->5
For k = 2, you should return: 2->1->4->3->5
For k = 3, you should return: 3->2->1->4->5

递归。找出前k个之后,后边的分下去做。我对这前k个逆序之后连接上后边的。

public ListNode reverseKGroup(ListNode head, int k) {
        if (k == 1) {
            return head;
        }
        int count = 0;
        ListNode cur = head;
        while (cur != null && count != k) {
            cur = cur.next;
            count++;
        }
        if (count == k) {
            ListNode prev = reverseKGroup(cur, k);
            while (head != cur) {
                ListNode temp = head.next;
                head.next = prev;
                prev = head;
                head = temp;
            }
            return prev;
        }
        return head;
    }
View Code

非递归。也是一段一段的找。

public ListNode reverseKGroup(ListNode head, int k) {
        if (k == 1) {
            return head;
        }
        ListNode cur = head;
        ListNode dummyHead = new ListNode(0);
        dummyHead.next = head;
        ListNode tail = dummyHead;
        while (cur != null) {
            int count = 0;
            while (cur != null && count != k) {
                cur = cur.next;
                count++;
            }
            if (count == k) {
                ListNode prev = cur;
                while (head != cur) {
                    ListNode temp = head.next;
                    head.next = prev;
                    prev = head;
                    head = temp;
                }
                ListNode tempNext = tail.next;
                tail.next = prev;
                tail = tempNext;
            }
        }
        return dummyHead.next;
    }
View Code

26.Remove Duplicates from Sorted Array

Given a sorted array, remove the duplicates in place such that each element appear only once and return the new length.

Do not allocate extra space for another array, you must do this in place with constant memory.

For example,
Given input array nums = [1,1,2],

Your function should return length = 2, with the first two elements of nums being 1 and 2 respectively. It doesn't matter what you leave beyond the new length.

two point.

public int removeDuplicates(int[] nums) {
        if (nums == null || nums.length == 0) {
            return 0;
        }
        int left = 0;
        int right = 1;
        int n = nums.length;
        while (right < n) {
            if (nums[right] != nums[left]) {
                swap(nums, ++left, right++);
            } else {
                right++;
            }
        }
        return left + 1;
    }
    public void swap(int[] nums, int left, int right) {
        int temp = nums[left];
        nums[left] = nums[right];
        nums[right] = temp;
    }
View Code

27.Remove Element

Given an array and a value, remove all instances of that value in place and return the new length.

Do not allocate extra space for another array, you must do this in place with constant memory.

The order of elements can be changed. It doesn't matter what you leave beyond the new length.

Example:
Given input array nums = [3,2,2,3], val = 3

Your function should return length = 2, with the first two elements of nums being 2.

two point.

public int removeElement(int[] nums, int val) {
        if (nums == null || nums.length == 0) {
            return 0;
        }
        int left = 0;
        int n = nums.length;
        int right = 0;
        while (right < n) {
            if (nums[right] != val) {
                swap(nums, left++, right++);
            } else {
                right++;
            }
        }
        return left;
    }
    public void swap(int[] nums, int left, int right) {
        int temp = nums[left];
        nums[left] = nums[right];
        nums[right] = temp;
    }
View Code

28.Implement strStr()

Implement strStr().

Returns the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack.

就是分别检测每个点起始的这个子串可不可以。

public int strStr(String haystack, String needle) {
        if (haystack == null || needle == null || haystack.length() < needle.length()) {
            return -1;
        }
        char[] chars1 = haystack.toCharArray();
        char[] chars2 = needle.toCharArray();
        int n1 = haystack.length();
        int n2 = needle.length();
        for (int i = 0; i + n2 <= n1; i++) {
            int j = 0;
            for (; j < n2; j++) {
                if (chars1[i + j] != chars2[j]) {
                    break;
                }
            }
            if (j == n2) {
                return i;
            }
        }
        return -1;
    }
View Code

 hash,只有hash值相等的时候才比较。O(n)

 public static final int BASE = 1000000;
    public int strStr(String haystack, String needle) {
        if (haystack == null || needle == null) {
            return -1;
        }
        if (needle.length() == 0) {
            return 0;
        }
        int hLen = haystack.length();
        int nLen = needle.length();
        int pow = 1;
        int targetCode = 0;
        char[] nChars = needle.toCharArray();
        for (int i = 0; i < nLen; i++) {
            if (i < nLen - 1) {
                pow = (pow * 31) % BASE;    
            }
            targetCode = (targetCode * 31 + nChars[i]) % BASE;
        }
        int hashCode = 0;
        char[] hChars = haystack.toCharArray();
        for (int i = 0; i < hLen; i++) {
            hashCode = (hashCode * 31 + hChars[i]) % BASE;
            if (i < nLen - 1) {
                continue;
            }
            if (targetCode == hashCode) {
                if (haystack.substring(i - nLen + 1, i + 1).equals(needle)) {
                    return i - nLen + 1;
                }
            } else {
                hashCode = (hashCode - pow * hChars[i - nLen + 1]) % BASE;
                if (hashCode < 0) {
                    hashCode += BASE;
                }
            }
        }
        return -1;
    }
View Code

29.Divide Two Integers

Divide two integers without using multiplication, division and mod operator.
If it is overflow, return MAX_INT.

二分。

public int divide(int dividend, int divisor) {
         if (divisor == 0) {
             return -1;
         }
         if (dividend == 0) {
             return 0;
         }
         long longdividend = (long)dividend;
         long longdivisor = (long)divisor;
         int count = 0;
         if (longdividend < 0) {
             longdividend = -longdividend;
             count++;
         }
         if (longdivisor < 0) {
             longdivisor = -longdivisor;
             count++;
         }
         long res = 0;
         while (longdividend >= longdivisor) {
             long base = longdivisor;
             long num = 1;
             while (longdividend >= base) {
                 res += num;
                 longdividend -= base;
                 base += base;
                 num += num;
             }
         }
         if(count % 2 != 0) {
             res = -res;
         }
         return res > Integer.MAX_VALUE ? Integer.MAX_VALUE : res < Integer.MIN_VALUE ? Integer.MIN_VALUE : (int)res;
    }
View Code

30.Substring with Concatenation of All Words

You are given a string, s, and a list of words, words, that are all of the same length. Find all starting indices of substring(s) in s that is a concatenation of each word in words exactly once and without any intervening characters.

For example, given:
s: "barfoothefoobarman"
words: ["foo", "bar"]

两层循环,外层循环为wordLen。内存一次取出长度为wordLen的子串,如果不在map中,表明不满足,移动到下一位;在里面的话,还有可能出现次数多了的问题。

public List<Integer> findSubstring(String s, String[] words) {
        List<Integer> res = new ArrayList<Integer>();
        if (res == null || words == null || s.length() == 0 || words.length == 0) {
            return res;
        }
        int sLen = s.length();
        int wordLen = words[0].length();
        int m = words.length;
        int winLen = wordLen * m;
        if (sLen < winLen) {
            return res;
        }
        HashMap<String, Integer> map = new HashMap<String, Integer>();
        for (String word : words) {
            map.put(word, map.getOrDefault(word, 0) + 1);
        }
        for (int i = 0; i < wordLen; i++) {
            int start = i;
            int j = i;
            int count = 0;
            HashMap<String, Integer> timesMap = new HashMap<String, Integer>();
            while (j + wordLen <= sLen) {
                if (start + winLen > sLen) {
                    break;
                }
                String str = s.substring(j, j + wordLen);
                if (!map.containsKey(str)) {
                    j += wordLen;
                    start = j;
                    timesMap.clear();
                    count = 0;
                    continue;
                } else {
                    timesMap.put(str, timesMap.getOrDefault(str, 0) + 1);
                    count++;
                    while (timesMap.get(str) > map.get(str)) {
                        String temp = s.substring(start, start + wordLen);
                        timesMap.put(temp, timesMap.get(temp) - 1);
                        start += wordLen;
                        count--;
                    }
                    if (count == m) {
                        res.add(start);
                        String temp = s.substring(start, start + wordLen);
                        timesMap.put(temp, timesMap.get(temp) - 1);
                        start += wordLen;
                        count--;
                    }
                    j += wordLen; // 容易忘记
                }
            }
        }
        return res;
    }
View Code

31.Next Permutation --- not bug free

Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers.

If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order).

The replacement must be in-place, do not allocate extra memory.

Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column.
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1

找到第一个左边比我小的,然后右半部分逆序。如果654321直接返回。不是的话,右半部分找到第一个  49876 比4大的,交换。

public void nextPermutation(int[] nums) {
        if (nums == null || nums.length < 2) {
            return;
        }
        int n = nums.length;
        int right = n - 1;
        while (right > 0 && nums[right] <= nums[right - 1]) {
            right--;
        }
        reverse(nums, right, n - 1);
        if (right != 0) {
            int index = findFirstBigger(nums, right, n - 1, nums[right - 1]);
            int temp = nums[right - 1];
            nums[right - 1] = nums[index];
            nums[index] = temp;
        }
    }
    public void reverse(int[] nums, int left, int right) {
        while (left < right) {
            int temp = nums[left];
            nums[left] = nums[right];
            nums[right] = temp;
            left++;
            right--;
        }
    }
    public int findFirstBigger(int[] nums, int start, int end, int target) {
        while (start + 1 < end) {
            int mid = start + (end - start) / 2;
            if (nums[mid] <= target) {
                start = mid;
            } else {
                end = mid;
            }
        }
        if (nums[start] > target) {
            return start;
        } else {
            return end;
        }
    }
View Code

32.Longest Valid Parentheses --- not bug free

Given a string containing just the characters '(' and ')', find the length of the longest valid (well-formed) parentheses substring.

For "(()", the longest valid parentheses substring is "()", which has length = 2.

Another example is ")()())", where the longest valid parentheses substring is "()()", which has length = 4.

主要是思想,实现很简单。动规:dp[i]表示以i结尾的有效括号串的长度。

public class Solution {
    public int longestValidParentheses(String s) {
        if (s == null || s.length() == 0) {
            return 0;
        }
        char[] chars = s.toCharArray();
        int n = s.length();
        int[] dp = new int[n]; // dp[i]表示以i结尾的最长有效串长度
        int res = 0;
        for (int i = 1; i < n; i++) {
            if (chars[i] == '(') {
                continue;
            } else {
                if (i- dp[i - 1] - 1 >= 0 && chars[i - dp[i - 1] - 1] == '(') {
                    dp[i] = dp[i - 1] + 2 + ((i - dp[i - 1] - 2 >= 0) ? dp[i - dp[i - 1] - 2] : 0);
                    res = Math.max(res, dp[i]);
                }
            }
        }
        return res;
    }
}
View Code

33.Search in Rotated Sorted Array

Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.

(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).

You are given a target value to search. If found in the array return its index, otherwise return -1.

You may assume no duplicate exists in the array.

根据nums[left]与nums[mid]大小关系分段,然后再看target在不在区间上。

public int search(int[] nums, int target) {
        if (nums == null || nums.length == 0) {
            return -1;
        }
        int left = 0;
        int right = nums.length - 1;
        while (left + 1 < right) {
            int mid = left + (right - left) / 2;
            if (nums[left] < nums[mid]) {
                if (nums[left] <= target && target <= nums[mid]) {
                    right = mid;
                } else {
                    left = mid;
                }
            } else {
                if (nums[mid] <= target && target <= nums[right]) {
                    left = mid;
                }  else {
                    right = mid;
                }
            }
        }
        if (nums[left] == target) {
            return left;
        }
        if (nums[right] == target) {
            return right;
        }
        return -1;
    }
View Code

34.Search for a Range

Given an array of integers sorted in ascending order, find the starting and ending position of a given target value.

Your algorithm's runtime complexity must be in the order of O(log n).

If the target is not found in the array, return [-1, -1].

For example,
Given [5, 7, 7, 8, 8, 10] and target value 8,
return [3, 4].

找第一个和最后一个相等的位置。

def searchRange(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        if not nums or len(nums) == 0:
            return [-1, -1]
        left = self.findFirstEqual(nums, target)
        if (left == -1):
            return [-1, -1]
        right = self.findFinalEqual(nums, target)
        return [left, right]
    def findFirstEqual(self, nums, target):
        left = 0;
        right = len(nums) - 1
        while (left + 1 < right):
            mid = left + (right - left) / 2
            if (nums[mid] < target):
                left = mid
            else:
                right = mid
        if nums[left] == target:
            return left
        elif nums[right] == target:
            return right
        else:
            return -1
    def findFinalEqual(self, nums, target):
        left = 0;
        right = len(nums) - 1
        while (left + 1 < right):
            mid = left + (right - left) / 2
            if (nums[mid] <= target):
                left = mid
            else:
                right = mid
        if nums[right] == target:
            return right
        elif nums[left] == target:
            return left
        else:
            return -1
View Code

35.Search Insert Position

Given a sorted array and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order.

You may assume no duplicates in the array.

Here are few examples.
[1,3,5,6], 5 → 2
[1,3,5,6], 2 → 1
[1,3,5,6], 7 → 4
[1,3,5,6], 0 → 0

找到第一个大于等于的位置。

def searchInsert(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        if not nums or len(nums) == 0:
            return -1
        return self.findFirstBiggerOrEqual(nums, target)
    def findFirstBiggerOrEqual(self, nums, target):
        start = 0
        end = len(nums) - 1
        while (start + 1 < end):
            mid = start + (end - start) / 2
            if (nums[mid] < target):
                start = mid
            else:
                end = mid
        if nums[start] >= target:
            return start
        elif nums[end] >= target:
            return end
        else:
            return len(nums)

  

 36.Valid Sudoku --- not bug free

Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules.

The Sudoku board could be partially filled, where empty cells are filled with the character '.'.

依次检测每行每列 小方块。用一个统一的接口来进行检测。

public boolean isValidSudoku(char[][] board) {
        if (board == null || board.length != 9) {
            return false;
        }
        for (int i = 0; i < 9; i++) {
            if (!isParticallyValid(board, i, i, 0, 8)) {
                return false;
            }
            if (!isParticallyValid(board, 0, 8, i, i)) {
                return false;
            }
        }
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                if (!isParticallyValid(board, 3 * i, 3 * i + 2, 3 * j, 3 * j + 2)) {
                    return false;
                }
            }
        }
        return true;
    }
    public boolean isParticallyValid(char[][] board, int row_begin, int row_end, int col_begin, int col_end) {
        HashSet<Character> set = new HashSet<Character>();
        for (int i = row_begin; i <= row_end; i++) {
            for (int j = col_begin; j <= col_end; j++) {
                if (board[i][j] == '.') {
                    continue;
                } else {
                    if (!set.add(board[i][j])) {
                        return false;
                    }
                }
            }
        }
        return true;
    }
View Code

37.Sudoku Solver --- not bug free

Write a program to solve a Sudoku puzzle by filling the empty cells.

Empty cells are indicated by the character '.'.

You may assume that there will be only one unique solution.

递归程序控制行,然后内部控制列。遇到 '.' 检测合适的char,填入之后深搜下去看看行不,不行的话下一个,都不行的话返回false

public void solveSudoku(char[][] board) {
        if (board == null || board.length != 9) {
            return;
        }
        solve(board, 0);
    }
    public boolean solve(char[][] board, int row_begin) {
        for (int i = row_begin; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                if (board[i][j] == '.') {
                    for (char c = '1'; c <= '9'; c++) {
                        if (isValid(board, i, j, c)) {
                            board[i][j] = c;
                            if (solve(board, i)) {
                                return true;
                            }
                            board[i][j] = '.';
                        }
                    }
                    return false;
                }
            }
        }
        return true;
    }
    public boolean isValid(char[][] board, int row, int col, char c) {
        for (int j = 0; j < 9; j++) {
            if (board[row][j] == c) {
                return false;
            }
        }
        for (int i = 0; i < 9; i++) {
            if (board[i][col] == c) {
                return false;
            }
        }
        for (int i = row / 3 * 3; i <= row / 3 * 3 + 2; i++) {
            for (int j = col / 3 * 3; j < col / 3 * 3+ 2; j++) {
                if (board[i][j] == c) {
                    return false;
                }
            }
        }
        return true;
    }
View Code

38.Count and Say

The count-and-say sequence is the sequence of integers beginning as follows:
1, 11, 21, 1211, 111221, ...

1 is read off as "one 1" or 11.
11 is read off as "two 1s" or 21.
21 is read off as "one 2, then one 1" or 1211.
Given an integer n, generate the nth sequence.

Note: The sequence of integers will be represented as a string.

就是按照规则来,一个一个的迭代。注意迭代过程中n--

public String countAndSay(int n) {
        String res = "1";
        while (n > 1) {
            char[] chars = res.toCharArray();
            StringBuilder sb = new StringBuilder();
            int start = 0;
            int i = 0;
            int m = chars.length;
            while (i < m) {
                while (i < m && chars[i] == chars[start]) {
                    i++;
                }
                int count = i - start;
                sb.append(count);
                sb.append(chars[start]);
                start = i;
            }
            res = sb.toString();
            n--;
        }
        return res;
    }
View Code

39.Combination Sum

Given a set of candidate numbers (C) (without duplicates) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.

The same repeated number may be chosen from C unlimited number of times.

DFS

public List<List<Integer>> combinationSum(int[] candidates, int target) {
        List<List<Integer>> res = new ArrayList<List<Integer>>();
        if (candidates == null || candidates.length == 0) {
            return res;
        }
        Arrays.sort(candidates);
        DFS(candidates, target, res, new ArrayList<Integer>(), 0);
        return res;
    }
    public void DFS(int[] candidates, int target, List<List<Integer>> res, List<Integer> cur, int index) {
        if (target == 0) {
            res.add(new ArrayList<Integer>(cur));
            return;
        }
        int n = candidates.length;
        for (int i = index; i < n; i++) {
            if (candidates[i] > target) {
                return;
            }
            cur.add(candidates[i]);
            DFS(candidates, target - candidates[i], res, cur, i);
            cur.remove(cur.size() - 1);
        }
    }
View Code

40.Combination Sum II

Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.

Each number in C may only be used once in the combination.

DFS

 public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        List<List<Integer>> res = new ArrayList<List<Integer>>();
        if (candidates == null || candidates.length == 0) {
            return res;
        }
        Arrays.sort(candidates);
        DFS(candidates, target, res, new ArrayList<Integer>(), 0);
        return res;
    }
    public void DFS(int[] candidates, int target, List<List<Integer>> res, List<Integer> cur, int index) {
        if (target == 0) {
            res.add(new ArrayList<Integer>(cur));
            return;
        }
        int n = candidates.length;
        for (int i = index; i < n; i++) {
            if (i != index && candidates[i] == candidates[i - 1]) {
                continue;
            }
            if (candidates[i] > target) {
                return;
            }
            cur.add(candidates[i]);
            DFS(candidates, target - candidates[i], res, cur, i + 1);
            cur.remove(cur.size() - 1);
        }
    }
View Code

41.First Missing Positive

Given an unsorted integer array, find the first missing positive integer.

For example,
Given [1,2,0] return 3,
and [3,4,-1,1] return 2.

Your algorithm should run in O(n) time and uses constant space.

实现很简单,主要是思想:可能的结果为1..n + 1,我们把nums[i]放到 i +  1 位置,然后遍历数组,检测nums[i]是否等于 i + 1。

交换的时候,如果遇到小于1的或者大于n的,或者位置上已经满足nums[i] = i + 1的就不用管。其他的如果换过去那个位置也满足条件了,也不用换,否则交换。

public int firstMissingPositive(int[] nums) {
        if (nums == null || nums.length == 0) {
            return 1;
        }
        int n = nums.length;
        for (int i = 0; i < n; i++) {
            if (nums[i] == i + 1 || nums[i] > n || nums[i] < 1) {
                continue;
            } else if (nums[nums[i] - 1] != nums[i]){
                int temp = nums[nums[i] - 1];
                nums[nums[i] - 1] = nums[i];
                nums[i] = temp;
                i--;
            }
        }
        for (int i = 0; i < n; i++) {
            if (nums[i] != i + 1) {
                return i + 1;
            }
        }
        return n + 1;
    }
View Code

42.Trapping Rain Water

Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining.

For example, 
Given [0,1,0,2,1,0,1,3,2,1,2,1], return 6.

找到最大后,最有两边分别求。有了最大就有了保障。

 public int trap(int[] height) {
        if (height == null || height.length == 0) {
            return 0;
        }
        int maxIndex = 0;
        int max = height[0];
        int n = height.length;
        for (int i = 1; i < n; i++) {
            if (height[i] > max) {
                max = height[i];
                maxIndex = i;
            }
        }
        int res = 0;
        int left = 0;
        for (int i = 1; i < maxIndex; i++) {
            if (height[i] < height[left]) {
                res += (height[left] - height[i]);
            } else {
                left = i;
            }
        }
        int right = n - 1;
        for (int i = right - 1; i > maxIndex; i--) {
            if (height[i] < height[right]) {
                res += (height[right] - height[i]);
            } else {
                right = i;
            }
        }
        return res;
    }
View Code

43.Multiply Strings --- not bug free

Given two non-negative integers num1 and num2 represented as strings, return the product of num1 and num2.
Note:
The length of both num1 and num2 is < 110.
Both num1 and num2 contains only digits 0-9.
Both num1 and num2 does not contain any leading zero.
You must not use any built-in BigInteger library or convert the inputs to integer directly.

因子 1 的第 i 位与因子 2 的第 j 位对乘积的影响是第 i + j 和第 i + j + 1 位,所以从后往前一位一位相乘。

public String multiply(String num1, String num2) {
        if (num1 == null || num1.length() == 0) {
            return num2;
        }
        if (num2 == null || num2.length() == 0) {
            return num1;
        }
        char[] chars1 = num1.toCharArray();
        char[] chars2 = num2.toCharArray();
        int m = chars1.length;
        int n = chars2.length;
        int[] values = new int[m + n];
        for (int i = m - 1; i >= 0; i--) {
            for (int j = n - 1; j >= 0; j--) {
                int p1 = i + j;
                int p2 = i + j + 1;
                int sum = (chars1[i] - '0') * (chars2[j] - '0') + values[p2];
                values[p1] += sum / 10;
                values[p2] = sum % 10;
            }
        }
        StringBuilder sb = new StringBuilder();
        for (int value : values) {
            if (sb.length() == 0 && value == 0) {
                continue;
            }
            sb.append(value);
        }
        return sb.length() ==0 ? "0" : sb.toString();
    }
View Code

44.Wildcard Matching

Implement wildcard pattern matching with support for '?' and '*'.

'?' Matches any single character.
'*' Matches any sequence of characters (including the empty sequence).

The matching should cover the entire input string (not partial).

The function prototype should be:
bool isMatch(const char *s, const char *p)

Some examples:
isMatch("aa","a") → false
isMatch("aa","aa") → true
isMatch("aaa","aa") → false
isMatch("aa", "*") → true
isMatch("aa", "a*") → true
isMatch("ab", "?*") → true
isMatch("aab", "c*a*b") → false

一种思路可以求出一个数的0~9倍,然后主要设计两个字符串求和。

另一种思路:dp.

public boolean isMatch(String s, String p) {
        if (s == null || p == null) {
            return false;
        }
        char[] sChars = s.toCharArray();
        char[] pChars = p.toCharArray();
        int m = s.length();
        int n = p.length();
        boolean[][] dp = new boolean[m + 1][n + 1]; // dp[i][j]表示s的前i个字符和p的前j个字符是否匹配
        dp[0][0] = true;
        for(int j = 1; j <= n && pChars[j - 1] == '*'; j++) {
            dp[0][j] = true;
        }
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                if (sChars[i - 1] == pChars[j - 1] || pChars[j - 1] == '?') {
                    dp[i][j] = dp[i - 1][j - 1];
                } else {
                    if (pChars[j - 1] == '*') {
                        dp[i][j] = dp[i][j - 1] || dp[i - 1][j - 1] || dp[i - 1][j];
                    }
                }
            }
        }
        return dp[m][n];
    }
View Code

45.Jump Game II

Given an array of non-negative integers, you are initially positioned at the first index of the array.

Each element in the array represents your maximum jump length at that position.

Your goal is to reach the last index in the minimum number of jumps.

For example:
Given array A = [2,3,1,1,4]

The minimum number of jumps to reach the last index is 2. (Jump 1 step from index 0 to 1, then 3 steps to the last index.)

方法一:dp。dp[i]表示到达第i个的最小步数。TLE

public int jump(int[] nums) {
        if (nums == null || nums.length == 0) {
            return 0;
        }
        int n = nums.length;
        int[] dp = new int[n]; // dp[i]表示到达i的最小步数
        for (int i = 1; i < n; i++) {
            dp[i] = Integer.MAX_VALUE;
            for (int j = 0; j < i; j++) {
                if (nums[j] + j >= i) {
                    dp[i] = Math.min(dp[i], dp[j] + 1);
                }
            }
        }
        return dp[n - 1];
    }
View Code

方法二:贪心 --- not bug free

public int jump(int[] nums) {
        if (nums == null || nums.length == 0) {
            return 0;
        }
        int edge = 0; // 当前步数可以到达哪儿
        int nextReach = nums[0]; // 当前步数加1最多可以的到达哪儿
        int step = 0;
        int n = nums.length;
        for (int i = 1; i < n; i++) {
            if (i > edge) {
                step++;
                edge = nextReach;
                if (edge >= n - 1) {
                    return step;
                }
            }
            nextReach = Math.max(nextReach, nums[i] + i);
            if (nextReach == i) {
                return Integer.MAX_VALUE;
            }
        }
        return step;
    }
View Code

46.Permutations

Given a collection of distinct numbers, return all possible permutations.

For example,
[1,2,3] have the following permutations:
[
  [1,2,3],
  [1,3,2],
  [2,1,3],
  [2,3,1],
  [3,1,2],
  [3,2,1]
]

DFS

public List<List<Integer>> permute(int[] nums) {
        List<List<Integer>> res = new ArrayList<List<Integer>>();
        if (nums == null || nums.length == 0) {
            return res;
        }
        int n = nums.length;
        boolean[] used = new boolean[n];
        help(nums ,res, new ArrayList<Integer>(), used);
        return res;
    }
    public void help(int[] nums, List<List<Integer>> res, List<Integer> cur, boolean[] used) {
        if (cur.size() == nums.length) {
            res.add(new ArrayList<Integer>(cur));
            return;
        }
        int n = nums.length;
        for (int i = 0; i < n; i++) {
            if (used[i]) {
                continue;
            }
            used[i] = true;
            cur.add(nums[i]);
            help(nums, res, cur, used);
            cur.remove(cur.size() - 1);
            used[i] = false;
        }
    }
View Code

47.Permutations II

Given a collection of numbers that might contain duplicates, return all possible unique permutations.

For example,
[1,1,2] have the following unique permutations:
[
  [1,1,2],
  [1,2,1],
  [2,1,1]
]

DFS.别忘了排序

public List<List<Integer>> permuteUnique(int[] nums) {
        List<List<Integer>> res = new ArrayList<List<Integer>>();
        if (nums == null || nums.length == 0) {
            return res;
        }
        int n = nums.length;
        Arrays.sort(nums);
        boolean[] used = new boolean[n];
        help(nums ,res, new ArrayList<Integer>(), used);
        return res;
    }
    public void help(int[] nums, List<List<Integer>> res, List<Integer> cur, boolean[] used) {
        if (cur.size() == nums.length) {
            res.add(new ArrayList<Integer>(cur));
            return;
        }
        int n = nums.length;
        for (int i = 0; i < n; i++) {
            if (used[i]) {
                continue;
            }
            if (i != 0 && nums[i] == nums[i - 1] && !used[i - 1]) {
                continue;
            }
            used[i] = true;
            cur.add(nums[i]);
            help(nums, res, cur, used);
            cur.remove(cur.size() - 1);
            used[i] = false;
        }
    }
View Code

48.Rotate Image

You are given an n x n 2D matrix representing an image.

Rotate the image by 90 degrees (clockwise).

Follow up:
Could you do this in-place?

先对角线旋转,再列调换。

public void rotate(int[][] matrix) {
        if (matrix == null || matrix.length == 0) {
            return;
        }
        reverse(matrix);
        exchange(matrix);
    }
    public void reverse(int[][] matrix) {
        int n = matrix.length;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < i; j++) {
                int temp= matrix[i][j];
                matrix[i][j] = matrix[j][i]; 
                matrix[j][i] = temp;
            }
        }
    }
    public void exchange(int[][] matrix) {
        int n = matrix.length;
        int left = 0;
        int right = n - 1;
        while (left < right) {
            for (int i = 0; i < n; i++) {
                int temp = matrix[i][left];
                matrix[i][left] = matrix[i][right];
                matrix[i][right] = temp;
            }
            left++;
            right--;
        }
    }
View Code

49.Group Anagrams

Given an array of strings, group anagrams together.

For example, given: ["eat", "tea", "tan", "ate", "nat", "bat"], 
Return:

[
  ["ate", "eat","tea"],
  ["nat","tan"],
  ["bat"]
]

相同的放在一个map key 下。排序之后判断相同不。

public class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        if (strs == null || strs.length == 0) {
            return new ArrayList<List<String>>();
        }
        HashMap<String, List<String>> map = new HashMap<String, List<String>>();
        for (String str : strs) {
            char[] chars = str.toCharArray();
            Arrays.sort(chars);
            String key = new String(chars);
            if (!map.containsKey(key)) {
                map.put(key, new ArrayList<String>());
            }
            map.get(key).add(str);
        }
        return new ArrayList<List<String>>(map.values());
    }
}
View Code

50.Pow(x, n) --- not bug free

Implement pow(x, n).

二分。注意次方为 -2147483648 的时候简单的变为负处理会有溢出问题。所以需要检测讨论。

public class Solution {
    public double myPow(double x, int n) {
        if (n == Integer.MIN_VALUE) {
            if (Math.abs(Math.abs(x) - 1) < 0.000001) {
                return 1;
            } else {
                return Math.abs(x) > 1 ? 0 : Integer.MAX_VALUE;
             }
        }
        if (n < 0) {
            return 1.0 / myPow(x, -n);
        }
        double res = 1;
        while (n > 0) {
            double cur = x;
            int times = 1;
            while (n >= times) {
                res *= cur;
                n -= times;
                cur *= cur;
                times += times;
            }
        }
        return res;
    }
}
View Code

 上边的检测比较麻烦,直接写为不需要检测的。

public double myPow(double x, int n) {
        if (n < 0) {
            return 1 / x * 1 / myPow(x, -(n + 1));
        }
        double res = 1;
        while (n > 0) {
            double cur = x;
            int times = 1;
            while (n >= times) {
                res *= cur;
                n -= times;
                cur *= cur;
                times += times;
            }
        }
        return res;
    }
View Code

51.N-Queens

The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other.

递归程序填充行。列检测,主对角线检测,副对角线检测 填充。

public List<List<String>> solveNQueens(int n) {
        List<List<String>> res = new ArrayList<List<String>>();
        char[] base = new char[n];
        Arrays.fill(base, '.');
        boolean[] col_used = new boolean[n];
        boolean[] diag1_used = new boolean[2 * n];
        boolean[] diag2_used = new boolean[2 * n];
        help(n, res, new ArrayList<String>(), base, 0, col_used, diag1_used, diag2_used);
        return res;
    }
    public void help(int n, List<List<String>> res, List<String> cur, char[] base, int row, 
            boolean[] col_used, boolean[] diag1_used, boolean[] diag2_used) {
        if (row == n) {
            res.add(new ArrayList<String>(cur));
            return;
        }
        for (int j = 0; j < n; j++) {
            if (!col_used[j] && !diag1_used[row + j] && !diag2_used[j - row + n - 1]) {
                col_used[j] = true;
                diag1_used[row + j] = true;
                diag2_used[j - row + n - 1] = true;
                base[j] = 'Q';
                cur.add(new String(base));
                base[j] = '.';
                help(n, res, cur, base, row + 1, col_used, diag1_used, diag2_used);
                col_used[j] = false;
                diag1_used[row + j] = false;
                diag2_used[j - row + n - 1] = false;
                cur.remove(cur.size() - 1);
            }
        }
    }
View Code

52.N-Queens II

Follow up for N-Queens problem.

Now, instead outputting board configurations, return the total number of distinct solutions.

同样的道理DFS

public int totalNQueens(int n) {
        int[] res = new int[1];
        boolean[] col_used = new boolean[n];
        boolean[] diag1_used = new boolean[2 * n];
        boolean[] diag2_used = new boolean[2 * n];
        help(n, res, col_used, diag1_used, diag2_used, 0);
        return res[0];
    }
    public void help(int n, int[] res, boolean[] col_used, boolean[] diag1_used, boolean[] diag2_used, int row) {
        if (n == row) {
            res[0]++;
            return;
        }
        for (int j = 0; j < n; j++) {
            if (!col_used[j] && !diag1_used[row + j] && !diag2_used[j - row + n - 1]) {
                col_used[j] = true;
                diag1_used[row + j] = true;
                diag2_used[j - row + n - 1] = true;
                help(n, res, col_used, diag1_used, diag2_used, row + 1);
                col_used[j] = false;
                diag1_used[row + j] = false;
                diag2_used[j - row + n - 1] = false;
            }
        }
    }
View Code

53.Maximum Subarray

Find the contiguous subarray within an array (containing at least one number) which has the largest sum.

For example, given the array [-2,1,-3,4,-1,2,1,-5,4],
the contiguous subarray [4,-1,2,1] has the largest sum = 6.

前缀和为负则更新为0,遍历一遍实时更新res

public int maxSubArray(int[] nums) {
        int res = Integer.MIN_VALUE;
        int cur = 0;
        for (int num : nums) {
            if (cur < 0) {
                cur = 0;
            }
            cur += num;
            res = Math.max(res, cur);
        }
        return res;
    }
View Code

54.Spiral Matrix --- not bug free

Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral order.

For example,
Given the following matrix:

[
 [ 1, 2, 3 ],
 [ 4, 5, 6 ],
 [ 7, 8, 9 ]
]
You should return [1,2,3,6,9,8,7,4,5].

从外到内,一层一层的添加。row_begin row_end col_begin col_end控制。注意代码中Attention部分。

public List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> res = new ArrayList<Integer>();
        if (matrix == null || matrix.length == 0) {
            return res;
        }
        int m = matrix.length;
        int n = matrix[0].length;
        help(matrix, res, 0, m - 1, 0, n - 1);
        return res;
    }
    public void help(int[][] matrix, List<Integer> res, int row_begin, int row_end, int col_begin, int col_end) {
        if (row_begin > row_end || col_begin > col_end) {
            return;
        }
        for (int j = col_begin; j <= col_end; j++) {
            res.add(matrix[row_begin][j]);
        }
        row_begin++;
        for (int i = row_begin; i <= row_end; i++) {
            res.add(matrix[i][col_end]);
        }
        col_end--;
        if (row_begin > row_end) { // Attention!
            return;
        }
        for (int j = col_end; j >= col_begin; j--) {
            res.add(matrix[row_end][j]);
        }
        row_end--;
        if (col_begin > col_end) { // Attention!
            return;
        }
        for (int i = row_end; i >= row_begin; i--) {
            res.add(matrix[i][col_begin]);
        }
        col_begin++;
        help(matrix, res, row_begin, row_end, col_begin, col_end);
    } 
View Code

55.Jump Game --- not bug free

Given an array of non-negative integers, you are initially positioned at the first index of the array.

Each element in the array represents your maximum jump length at that position.

Determine if you are able to reach the last index.

贪心算法。max_reach记录最远可以到达的地方。注意中途不可到达检测的返回(见代码Attention)

public boolean canJump(int[] nums) {
        if (nums == null || nums.length == 0) {
            return false;
        }
        int max_reach = 0;
        int n = nums.length;
        for (int i = 0; i < n; i++) {
            if (max_reach < i) { // Attention!
                return false;
            }
            max_reach = Math.max(max_reach, nums[i] + i);
            if (max_reach >= n - 1) {
                return true;
            }
        }
        return false;
    }
View Code

56.Merge Intervals

Given a collection of intervals, merge all overlapping intervals.

For example,
Given [1,3],[2,6],[8,10],[15,18],
return [1,6],[8,10],[15,18].

方法一:使用stack

public List<Interval> merge(List<Interval> intervals) {
        LinkedList<Interval> res = new LinkedList<Interval>();
        if (intervals == null || intervals.size() == 0) {
            return res;
        }
        Collections.sort(intervals, new Comparator<Interval>() {
           public int compare(Interval i1, Interval i2) {
                return i1.start - i2.start;
            } 
        });
        Stack<Interval> stack = new Stack<Interval>();
        for (Interval interval : intervals) {
            if (stack.isEmpty()) {
                stack.push(interval);
            } else {
                if (stack.peek().end < interval.start) {
                    stack.push(interval);
                } else {
                    Interval top = stack.pop();
                    stack.push(new Interval(top.start, Math.max(top.end, interval.end)));
                }
            }
        }
        while (!stack.isEmpty()) {
            res.addFirst(stack.pop());
        }
        return res;
    }
View Code

方法二:使用stack多余了,直接遍历一遍就可以了。

public List<Interval> merge(List<Interval> intervals) {
        if (intervals == null || intervals.size() < 2) {
            return intervals;
        }
        Collections.sort(intervals, new Comparator<Interval>() {
           public int compare(Interval i1, Interval i2) {
               return i1.start - i2.start;
           } 
        });
        List<Interval> res = new ArrayList<Interval>();
        int start = intervals.get(0).start;
        int end = intervals.get(0).end;
        for (Interval interval : intervals) {
            if (interval.start > end) {
                res.add(new Interval(start, end));
                start = interval.start;
                end = interval.end;
            } else {
                end = Math.max(end, interval.end);
            }
        }
        res.add(new Interval(start, end));
        return res;
     }
View Code

57.Insert Interval   --- not bug free

Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessary).
You may assume that the intervals were initially sorted according to their start times.

一种方法当然是直接遍历一遍即可。

另外一种是二分。找到第一个end比新区间左边大于等于的,找到第一个start比新区间右边大于的。 

public List<Interval> insert(List<Interval> intervals, Interval newInterval) {
        List<Interval> res = new ArrayList<Interval>();
        if (intervals == null) {
            return res;
        }
        int left = findFirstBiggerOrEqual(intervals, newInterval.start); // 第一个end比新区间左边大于等于的
        int right = findFirstBigger(intervals, newInterval.end); // 第一个start比新区间右边大于的
        if (left == right) {
            intervals.add(left, newInterval);
            return intervals;
        } else {
            for (int i = 0; i < left; i++) {
                res.add(intervals.get(i));
            }
            int start = Math.min(newInterval.start, intervals.get(left).start);
            int end = Math.max(newInterval.end, intervals.get(right - 1).end);
            res.add(new Interval(start, end));
            for (int i = right; i < intervals.size(); i++) {
                res.add(intervals.get(i));
            }
            return res;
        }
    }
    public int findFirstBiggerOrEqual(List<Interval> intervals, int target) {
        if (intervals.size() == 0) {
            return 0;
        }
        int start = 0;
        int end = intervals.size() - 1;
        while (start + 1 < end) {
            int mid = start + (end - start) / 2;
            if (intervals.get(mid).end < target) {
                start = mid;
            } else {
                end = mid;
            }
        }
        if (intervals.get(start).end >= target) {
            return start;
        } else if (intervals.get(end).end >= target) {
            return end;
        } else {
            return intervals.size();
        }
    }
    public int findFirstBigger(List<Interval> intervals, int target) {
        if (intervals.size() == 0) {
            return 0;
        }
        int start = 0;
        int end = intervals.size() - 1;
        while (start + 1 < end) {
            int mid = start + (end - start) / 2;
            if (intervals.get(mid).start <= target) {
                start = mid;
            } else {
                end = mid;
            }
        }
        if (intervals.get(start).start > target) {
            return start;
        } else if (intervals.get(end).start > target) {
            return end;
        } else {
            return intervals.size();
        }
    }
View Code

58.Length of Last Word

Given a string s consists of upper/lower-case alphabets and empty space characters ' ', return the length of last word in the string.
If the last word does not exist, return 0.

由后往前遍历一遍就可以了

public int lengthOfLastWord(String s) {
        if (s == null || s.length() == 0) {
            return 0;
        }
        s = s.trim();
        char[] chars = s.toCharArray();
        int n = chars.length;
        int res = 0;
        for (int i = n - 1; i >= 0; i--) {
            if (chars[i] == ' ') {
                return res;
            }
            res++;
        }
        return res;
    }
View Code

59.Spiral Matrix II

Given an integer n, generate a square matrix filled with elements from 1 to n2 in spiral order.

For example,
Given n = 3,

You should return the following matrix:
[
 [ 1, 2, 3 ],
 [ 8, 9, 4 ],
 [ 7, 6, 5 ]
]

和Spiral Matrix一样的道理。

public int[][] generateMatrix(int n) {
        int[][] res = new int[n][n];
        fill(res, 0, n - 1, 0, n - 1, 1);
        return res;
    }
    public void fill(int[][] res, int row_start, int row_end, int col_start, int col_end, int num) {
        if (row_start > row_end || col_start > col_end) {
            return;
        }
        for (int j = col_start; j <= col_end; j++) {
            res[row_start][j] = num++;
        }
        row_start++;
        for (int i = row_start; i <= row_end; i++) {
            res[i][col_end] = num++;
        }
        col_end--;
        if (row_start > row_end) {
            return;
        }
        for (int j = col_end; j >= col_start; j--) {
            res[row_end][j] = num++;
        }
        row_end--;
        if (col_start > col_end) {
            return;
        }
        for (int i = row_end; i >= row_start; i--) {
            res[i][col_start] = num++;
        }
        col_start++;
        fill(res, row_start, row_end, col_start, col_end, num);
    }
View Code

60.Permutation Sequence --- not bug free

The set [1,2,3,…,n] contains a total of n! unique permutations.

By listing and labeling all of the permutations in order,
We get the following sequence (ie, for n = 3):

"123"
"132"
"213"
"231"
"312"
"321"
Given n and k, return the kth permutation sequence.

依次确定每一位上的数字。

1, 2 3 4

2, 1 3 4

3, 1 2 4

4, 1 2 3

k / 阶乘即可确定在哪一堆,即可确定当前数。同理,可以确定所有位上的数。

public String getPermutation(int n, int k) {
        int[] factors = new int[n + 1];
        factors[0] = 1;
        for (int i = 1; i <= n; i++) {
            factors[i] = factors[i - 1] * i;
        }
        List<Integer> nums = new ArrayList<Integer>();
        for (int i = 1; i <= n; i++) {
            nums.add(i);
        }
        StringBuilder sb = new StringBuilder();
        k--;
        for (int i = 1; i <= n; i++) { // 每一轮循环确定第i位数
            int index = k / factors[n - i];
            sb.append(nums.get(index));
            nums.remove(index);
            k -= index * factors[n - i];
        }
        return sb.toString();
    }
View Code

61.Rotate List --- not bug free

Given a list, rotate the list to the right by k places, where k is non-negative.

For example:
Given 1->2->3->4->5->NULL and k = 2,
return 4->5->1->2->3->NULL.

首先求出链表长度count,k % count

然后通过指针找到翻转的上一个结点

然后就是一些变换指针的操作

public ListNode rotateRight(ListNode head, int k) {
        if (head == null) {
            return head;
        }
        ListNode left = head;
        ListNode right = head;
        int count = 0;
        while (right != null) {
            count++;
            right = right.next;
        }
        k %= count;
        right = head;
        for (int i = 0; i < k; i++) {
            right = right.next;
        }
        if (right == left) {
            return head;
        }
        while (right.next != null) {
            right = right.next;
            left = left.next;
        }
        right.next = head;
        ListNode temp = left.next;
        left.next = null;
        return temp;
    }
View Code

如果长度过长,k较小的话,上述方法效率较低。所以直接在求长度循环中,加入条件,如果节点数已经到达k,则直接结束循环。

public ListNode rotateRight(ListNode head, int k) {
        if (head == null) {
            return head;
        }
        ListNode left = head;
        ListNode right = head;
        int count = 0;
        while (right != null && count != k) { // 未遍历完,数目已经达到k个也会停止
            count++;
            right = right.next;
        }
        if (right == null && count == k) { // 刚好有k个结点
            return head;
        }
        if (count < k) {
            k %= count;
            if (k == 0) { // k的整数倍结点
                return head;
            }
            right = head;
            for (int i = 0; i < k; i++) {
                right = right.next;
            }
        }
        while (right.next != null) {
            right = right.next;
            left = left.next;
        }
        right.next = head;
        ListNode temp = left.next;
        left.next = null;
        return temp;
    }
View Code

62.Unique Paths

A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below).

The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below).

How many possible unique paths are there?

方法一:二维DP

public int uniquePaths(int m, int n) {
        int[][] dp = new int[m][n]; // dp[i][j]表示[0, 0]到达[i, j]的方案数
        for (int j = 0; j < n; j++) {
            dp[0][j] = 1;
        }
        for (int i = 1; i < m; i++) {
            dp[i][0] = 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];
    }
View Code

方法二:滚动数组优化

public int uniquePaths(int m, int n) {
        int[][] dp = new int[2][n];
        for (int j = 0; j < n; j++) {
            dp[0][j] = 1;
        }
        for (int i = 1; i < m; i++) {
            dp[i % 2][0] = 1;
            for (int j = 1; j < n; j++) {
                dp[i % 2][j] = dp[(i - 1) % 2][j] + dp[i % 2][j - 1];
            }
        }
        return dp[(m - 1) % 2][n - 1];
    }
View Code

方法三:Math  C(m + n - 2, n - 1)

public int uniquePaths(int m, int n) {
        if (m > n) {
            int temp = m;
            m = n;
            n = temp;
        }
        long res = 1;
        for (int i = 1; i < m; i++) {
            res = res * (i + n - 1) / i;
        }
        return (int)res;
    }
View Code

63.Unique Paths II

Follow up for "Unique Paths":

Now consider if some obstacles are added to the grids. How many unique paths would there be?

An obstacle and empty space is marked as 1 and 0 respectively in the grid.

For example,
There is one obstacle in the middle of a 3x3 grid as illustrated below.

[
  [0,0,0],
  [0,1,0],
  [0,0,0]
]

一样的道理。只不过数学方法不能使用了

public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        int m = obstacleGrid.length;
        int n = obstacleGrid[0].length;
        int[][] dp = new int[2][n];
        for (int j = 0; j < n && obstacleGrid[0][j] == 0; j++) {
            dp[0][j] = 1;
        }
        for (int i = 1; i < m; i++) {
            if (obstacleGrid[i][0] == 0) {
                dp[i % 2][0] = dp[(i - 1) % 2][0];
            } else {
                dp[i % 2][0] = 0;
            }
            for (int j = 1; j < n; j++) {
                if (obstacleGrid[i][j] == 1) {
                    dp[i % 2][j] = 0;
                } else {
                    dp[i % 2][j] = dp[(i - 1) % 2][j] + dp[i % 2][j - 1];
                }
            }
        }
        return dp[(m - 1) % 2][n - 1];
    }
View Code

64.Minimum Path Sum

Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path.

Note: You can only move either down or right at any point in time.

同理DP

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

65.Valid Number

Validate if a given string is numeric.

Some examples:
"0" => true
" 0.1 " => true
"abc" => false
"1 a" => false
"2e10" => true
Note: It is intended for the problem statement to be ambiguous. You should gather all requirements up front before implementing one.

可能出现的字符有 数字 . e + -

必须有数字出现

e前边必须有数字 e后边必须有数字 e只能出现一次

.前边不能有e .只能出现一次

+ -只能出现在开头或者e后边

public boolean isNumber(String s) {
        if (s == null) {
            return false;
        }
        s = s.trim();
        char[] chars = s.toCharArray();
        boolean numSeen = false;
        boolean numAfterE = false;
        boolean eSeen = false;
        boolean dotSeen = false;
        int n = s.length();
        for (int i = 0; i < n; i++) {
            char c = chars[i];
            if (Character.isDigit(c)) {
                numSeen = true;
                numAfterE = true;
            } else if (c == 'e') {
                if (eSeen || !numSeen) {
                    return false;
                }
                eSeen = true;
                numAfterE = false;
            } else if (c == '.'){
                if (eSeen || dotSeen) {
                    return false;
                }
                dotSeen = true;
            } else if (c == '+' || c == '-') {
                if (i != 0 && chars[i - 1] != 'e') {
                    return false;
                }
            } else {
                return false;
            }
        }
        return numSeen && numAfterE;
    }
View Code

66.Plus One

Given a non-negative integer represented as a non-empty array of digits, plus one to the integer.

You may assume the integer do not contain any leading zero, except the number 0 itself.

The digits are stored such that the most significant digit is at the head of the list.

直接从后往前 carry携带进位就可以了

def plusOne(self, digits):
        """
        :type digits: List[int]
        :rtype: List[int]
        """
        if not digits:
            return digits
        res = []
        carry = 1
        n = len(digits) - 1
        for i in xrange(n, -1, -1):
            temp = carry + digits[i]
            res.insert(0, temp % 10)
            carry = temp / 10
        if carry == 1:
            res.insert(0, 1)
        return res
View Code

直接原数组上操作

def plusOne(self, digits):
        """
        :type digits: List[int]
        :rtype: List[int]
        """
        if not digits:
            return digits
        carry = 1
        n = len(digits) - 1
        for i in xrange(n, -1, -1):
            temp = carry + digits[i]
            digits[i] = temp % 10
            carry = temp / 10
            if carry == 0:
                break
        if carry == 1:
            digits.insert(0, 1)
        return digits
View Code

67.Add Binary

Given two binary strings, return their sum (also a binary string).

For example,
a = "11"
b = "1"
Return "100".

从后开始,当前位为异或,carry当1的个数大于等于2为正

def addBinary(self, a, b):
        """
        :type a: str
        :type b: str
        :rtype: str
        """
        if not a:
            return b
        if not b:
            return a
        m = len(a) - 1
        n = len(b) - 1
        carry = 0
        res = ""
        while m >= 0 or n >= 0 or carry != 0:
            oneNum = carry
            if m >= 0:
                carry ^= int(a[m])
                if a[m] == '1':
                    oneNum += 1
            if n >= 0:
                carry ^= int(b[n])
                if b[n] == '1':
                    oneNum += 1
            res = str(carry) + res
            carry = 1 if oneNum >= 2 else 0
            m -= 1
            n -= 1
        return res
View Code

68.Text Justification --- not bug free

Given an array of words and a length L, format the text such that each line has exactly L characters and is fully (left and right) justified.

You should pack your words in a greedy approach; that is, pack as many words as you can in each line. Pad extra spaces ' ' when necessary so that each line has exactly L characters.

Extra spaces between words should be distributed as evenly as possible. If the number of spaces on a line do not divide evenly between words, the empty slots on the left will be assigned more spaces than the slots on the right.

For the last line of text, it should be left justified and no extra space is inserted between words.

For example,
words: ["This", "is", "an", "example", "of", "text", "justification."]
L: 16.

遍历原来的字符串数组,prevLen 和 afterLen分别表示不加和加上当前这个单词后的长度。

如果 afterLen <= maxDepth:

  如果已经到达最后一个单词,那个直接处理即可

  如果没有达到,那么prevLen更新为afterLen,继续下一个

afterLen > maxDepth:

  表明当前这个不能连上,所以处理前边的,处理前边时候由于涉及除以(end - start),所以对于一个单词的情况单独处理

def fullJustify(self, words, maxWidth):
        """
        :type words: List[str]
        :type maxWidth: int
        :rtype: List[str]
        """
        if not words:
            return []
        res = []
        prevLen = 0
        afterLen = 0
        n = len(words)
        start = 0
        i = 0
        while i < n:
            afterLen = prevLen + len(words[i]) + (0 if prevLen == 0 else 1)
            if afterLen <= maxWidth:
                if i == n - 1: # 到达最后一行
                    cur = ""
                    for j in xrange(start, i):
                        cur += words[j] + " "
                    cur += words[i]
                    cur += " " * (maxWidth - afterLen)
                    res.append(cur)
                    return res
                else:
                    prevLen = afterLen
                    i += 1
            else:
                end = i - 1
                if end - start == 0: # 一个单词占一行
                    cur = words[start]
                    cur += " " * (maxWidth - prevLen)
                    res.append(cur)
                else:
                    space_total = maxWidth - prevLen
                    space_one = space_total / (end - start)
                    space_ugly = space_total % (end - start)
                    cur = ""
                    for j in xrange(start, end):
                        if space_ugly > 0:
                            cur = cur + words[j] + " " * (space_one + 2)
                            space_ugly -= 1
                        else:
                            cur = cur + words[j] + " " * (space_one + 1)
                    cur += words[end]
                    res.append(cur)
                prevLen = 0
                start = i
        return res
View Code

 69.Sqrt(x)

Implement int sqrt(int x).

Compute and return the square root of x.

二分。

def mySqrt(self, x):
        """
        :type x: int
        :rtype: int
        """
        start = 0
        end = x
        while start + 1 < end:
            mid = (start + end) / 2
            square = mid * mid
            if square < x:
                start = mid
            elif square > x:
                end = mid
            else:
                return mid
        if end * end <= x:
            return end
        else:
            return start
View Code

70.Climbing Stairs

You are climbing a stair case. It takes n steps to reach to the top.

Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?
def climbStairs(self, n):
        """
        :type n: int
        :rtype: int
        """
        if n == 0:
            return 1
        if n <= 2:
            return n
        prevOne = 2
        prevTwo = 1
        for i in range(2, n):
            temp = prevOne
            prevOne = prevOne + prevTwo
            prevTwo = temp
        return prevOne
View Code

71.Simplify Path

Given an absolute path for a file (Unix-style), simplify it.

For example,
path = "/home/", => "/home"
path = "/a/./b/../../c/", => "/c"
View Code

使用stack。'..'弹出; '.' 不处理;'//'和'/'效果一样

def simplifyPath(self, path):
        """
        :type path: str
        :rtype: str
        """
        if not path:
            return None
        strs = path.split("/")
        # print len(strs)
        stack = []
        for str in strs:
            if str == '..' and stack:
                stack.pop()
            elif str != '..' and str != '.' and str != '':
                stack.append(str)
        res = ''
        for str in stack:
            res += str + '/'
        res = '/' + res.strip('/')
        return res
View Code

 72.Edit Distance

Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2. (each operation is counted as 1 step.)

You have the following 3 operations permitted on a word:

a) Insert a character
b) Delete a character
c) Replace a character

dp.

 def minDistance(self, word1, word2):
        """
        :type word1: str
        :type word2: str
        :rtype: int
        """
        if not word1 and not word2:
            return 0
        m = len(word1)
        n = len(word2)
        dp = [[0 for i in range(n + 1)] for j in range(m + 1)]
        for i in range(n + 1):
            dp[0][i] = i
        for i in range(m + 1):
            dp[i][0] = i
        for i in range(1, m + 1):
            for j in range(1, n + 1):
                if word1[i - 1] == word2[j - 1]:
                    dp[i][j] = dp[i - 1][j - 1]
                else:
                    dp[i][j] = min(dp[i][j - 1], dp[i - 1][j], dp[i - 1][j - 1]) + 1
        return dp[m][n]
View Code

 73.Set Matrix Zeroes --- not bug free

Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in place.

click to show follow up.

Follow up:
Did you use extra space?
A straight forward solution using O(mn) space is probably a bad idea.
A simple improvement uses O(m + n) space, but still not the best solution.
Could you devise a constant space solution?

用第一行第一列来记录这行这列是否有"0",但是首先需要一个boolean来记录最开始的第一行第一列时候本身就有0。注意代码中Attention部分

def setZeroes(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: void Do not return anything, modify matrix in-place instead.
        """
        if not matrix:
            return
        m = len(matrix)
        n = len(matrix[0])
        firstRow = False
        firstCol = False
        for j in xrange(n):
            if matrix[0][j] == 0:
                firstRow = True
                break
        for i in xrange(m):
            if matrix[i][0] == 0:
                firstCol = True
                break
        for i in xrange(m):
            for j in xrange(n):
                if matrix[i][j] == 0:
                    matrix[i][0] = 0
                    matrix[0][j] = 0
        for i in xrange(1, m): # Attention
            if matrix[i][0] == 0:
                self.setRowZero(matrix, i)
        for j in xrange(1, n): # Attention
            if matrix[0][j] == 0:
                self.setColZero(matrix, j)
        if firstRow:
            self.setRowZero(matrix, 0)
        if firstCol:
            self.setColZero(matrix, 0)
    def setColZero(self, matrix, col):
        m = len(matrix)
        for i in range(m):
            matrix[i][col] = 0
    def setRowZero(self, matrix, row):
        n = len(matrix[0])
        for j in range(n):
            matrix[row][j] = 0
View Code

 74.Search a 2D Matrix

Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties:

Integers in each row are sorted from left to right.
The first integer of each row is greater than the last integer of the previous row.

二分。

def searchMatrix(self, matrix, target):
        """
        :type matrix: List[List[int]]
        :type target: int
        :rtype: bool
        """
        if not matrix:
            return False
        m = len(matrix)
        n = len(matrix[0])
        if m == 0 or n == 0:
            return False
        start = 0
        end = m * n - 1
        while start + 1 < end:
            mid = (start + end) / 2
            num = matrix[mid / n][mid % n]
            if num == target:
                return True
            elif num < target:
                start = mid
            else:
                end = mid
        return matrix[start / n][start % n] == target or matrix[end / n][end % n] == target
View Code

75.Sort Colors

Given an array with n objects colored red, white or blue, sort them so that objects of the same color are adjacent, with the colors in the order red, white and blue.

Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively.

两边两个指针控制,中间index移动。注意的是,左边换过去的时候,index也要+1,如代码Attention所示

def sortColors(self, nums):
        """
        :type nums: List[int]
        :rtype: void Do not return anything, modify nums in-place instead.
        """
        if not nums:
            return
        n = len(nums)
        left = 0
        right = n - 1
        index = 0
        while index <= right:
            if nums[index] == 0:
                temp = nums[left]
                nums[left] = nums[index]
                nums[index] = temp
                left += 1
                index += 1 # Attention!
            elif nums[index] == 2:
                temp = nums[right]
                nums[right] = nums[index]
                nums[index] = temp
                right -= 1
            else:
                index += 1
View Code

 76.Minimum Window Substring

Given a string S and a string T, find the minimum window in S which will contain all the characters in T in complexity O(n).

For example,
S = "ADOBECODEBANC"
T = "ABC"
Minimum window is "BANC".

和第30题比较接近,区别是这里允许有无关字符的出现。

用一个map记录tLen中字符的出现。然后遍历sLen,二话不说,map对应位置先减,如果减了之后大于等于0,表明这是一个“有用的”,更新count。当count为0的时候,更新结果。并且二话不说先加,如果加完后map[start] > 0,表明这是一个有用的,更新count。

def minWindow(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: str
        """
        if not s or not t:
            return ""
        sLen = len(s)
        tLen = len(t)
        if sLen < tLen:
            return ""
        map = [0] * 128
        for c in t:
            map[ord(c)] += 1
        minStart = 0
        minEnd = sLen
        start = 0
        count = tLen
        for i in xrange(sLen):
            map[ord(s[i])] -= 1
            if map[ord(s[i])] >= 0:
                count -= 1
            while count == 0:
                if i - start < minEnd - minStart:
                    minStart = start
                    minEnd = i
                map[ord(s[start])] += 1
                if map[ord(s[start])] > 0:
                    count += 1
                start += 1
                if start + tLen > sLen:
                    break
        if minStart == 0 and minEnd == sLen:
            return ""
        else:
            return s[minStart:minEnd + 1]
View Code

 77.Combinations

Given two integers n and k, return all possible combinations of k numbers out of 1 ... n.

For example,
If n = 4 and k = 2, a solution is:

[
  [2,4],
  [3,4],
  [2,3],
  [1,2],
  [1,3],
  [1,4],
]

注意代码中Attention部分的处理。当剩余的个数加起来达不到k个的时候,就不需要再深搜下去,这可以节约很多时间。否则TLE了

def combine(self, n, k):
        """
        :type n: int
        :type k: int
        :rtype: List[List[int]]
        """
        res = []
        if n < k:
            return res
        self.dfs(n, k, res, [], 1)
        return res
    def dfs(self, n, k, res, cur, index):
        if len(cur) == k:
            res.append(cur[:])
            return
        for i in xrange(index, n + 1):
            if (n - i + 1 + len(cur) < k): # Attention!
                break;
            cur.append(i)
            self.dfs(n, k, res, cur, i + 1)
            cur.pop()
View Code

78.Subsets

Given a set of distinct integers, nums, return all possible subsets.

DFS

def subsets(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        res = []
        if not nums:
            return res
        self.dfs(nums, 0, res, [])
        return res
    def dfs(self, nums, index, res, cur):
        res.append(cur[:])
        n = len(nums)
        for i in xrange(index, n):
            cur.append(nums[i])
            self.dfs(nums, i + 1, res, cur)
            cur.pop()
View Code

79.Word Search

Given a 2D board and a word, find if the word exists in the grid.

The word can be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once.

DFS.

 def exist(self, board, word):
        """
        :type board: List[List[str]]
        :type word: str
        :rtype: bool
        """
        if not board or not word:
            return False
        m = len(board)
        n = len(board[0])
        if m * n < len(word):
            return False
        for i in xrange(m):
            for j in xrange(n):
                if self.dfs(board, word, i, j, 0):
                    return True;
        return False
    def dfs(self, board, word, i, j, index):
        m = len(board)
        n = len(board[0])
        if index == len(word):
            return True
        if i < 0 or i >= m:
            return False
        if j < 0 or j >= n:
            return False
        if board[i][j] != word[index]:
            return False
        temp = board[i][j]
        board[i][j] = '.'
        res =  self.dfs(board, word, i + 1, j, index + 1) 
            or self.dfs(board, word, i - 1, j, index + 1) 
            or self.dfs(board, word, i, j + 1, index + 1) 
            or self.dfs(board, word, i, j - 1, index + 1)
        board[i][j] = temp
        return res
View Code

80.Remove Duplicates from Sorted Array II

Follow up for "Remove Duplicates":
What if duplicates are allowed at most twice?

For example,
Given sorted array nums = [1,1,1,2,2,3],

Your function should return length = 5, with the first five elements of nums being 1, 1, 2, 2 and 3. It doesn't matter what you leave beyond the new length.

times记录次数,首先start = 0 times = 1,start位置表示已经满足了。然后遍历数组,如果nums[i] == nums[start] and times >= 2表明不可加进来,否则可以加进来。加进来要看nums[i]和nums[start]的关系控制times的取值变化。然后start + 1后值换过来。

def removeDuplicates(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if not nums:
            return 0
        n = len(nums)
        start = 0
        times = 1
        for i in xrange(1, n):
            if nums[i] == nums[start] and times >= 2:
                continue
            else:
                if nums[i] == nums[start]:
                    times += 1
                else:
                    times = 1
                start += 1
                nums[start] = nums[i]
        return start + 1
View Code

81.Search in Rotated Sorted Array II

Follow up for "Search in Rotated Sorted Array":
What if duplicates are allowed?

Would this affect the run-time complexity? How and why?

允许重复了,那么其实最坏的复杂度就会达到O(n)了。这里首先移动start,让nums[start] != nums[end]是为了保证:如果nums[start] <= nums[mid],那么[start, mid]一定是单增的,然后分段来考虑. 1 3 1 1 1

def search(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: bool
        """
        if not nums:
            return False
        n = len(nums)
        start = 0
        end = n - 1
        while start < end and nums[start] == nums[end]: # 保证start到mid一定是单增的
            start += 1
        while start + 1 < end:
            mid = (start + end) / 2
            if nums[start] <= nums[mid]:
                if nums[start] <= target and target <= nums[mid]:
                    end = mid
                else:
                    start = mid
            else:
                if nums[mid] <= target and target <= nums[end]:
                    start = mid
                else:
                    end = mid
        return nums[start] == target or nums[end] == target
View Code

 82.Remove Duplicates from Sorted List II

Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list.

For example,
Given 1->2->3->3->4->4->5, return 1->2->5.
Given 1->1->1->2->3, return 2->3.

有重复往后走,最后看tail.next是否等于head,等的话表明head位置这个值满足条件,不等的话不满足。

 def deleteDuplicates(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        if not head:
            return head
        dummyHead = ListNode(0)
        dummyHead.next = head
        tail = dummyHead
        while head:
            while head.next and head.val == head.next.val:
                head = head.next
            if tail.next == head:
                tail = head
                head = head.next
            else:
                head = head.next
                tail.next = head
        return dummyHead.next
View Code

83.Remove Duplicates from Sorted List

Given a sorted linked list, delete all duplicates such that each element appear only once.

For example,
Given 1->1->2, return 1->2.
Given 1->1->2->3->3, return 1->2->3.

现在允许重复的出现一次就更好办了。如果cur.val == cur.next.val 那么 cur.next = cur.next.next

def deleteDuplicates(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        if not head:
            return head
        cur = head
        while cur:
            tmp = cur.val
            while cur.next and cur.next.val == tmp:
                cur.next = cur.next.next
            cur = cur.next
        return head
View Code

 84.Largest Rectangle in Histogram

Given n non-negative integers representing the histogram's bar height where the width of each bar is 1, find the area of largest rectangle in the histogram.

方法一:最大直方图面积,递增栈。新来的元素如果大于栈顶元素,那么压入栈,小于等于栈顶元素,表明此时栈顶元素的右边界已经找到,弹出后的新栈顶就是之前栈顶的左边界。注意栈中存储的是下标,最后需要一个统一弹出,计算下标区间长度的时候不包含端点。

def largestRectangleArea(self, heights):
        """
        :type heights: List[int]
        :rtype: int
        """
        if not heights:
            return 0
        s = []
        n = len(heights)
        res = 0
        s.append(-1)
        for i in xrange(n + 1):
            cur = (-1 << 31) if i == n else heights[i]
            if len(s) == 1 or heights[s[-1]] < cur:
                s.append(i)
            else:
                while len(s) > 1 and heights[s[-1]] >= cur:
                    index = s.pop()
                    res = max(res, (i - s[-1] - 1) * heights[index])
                s.append(i)
        return res
View Code

 方法二:DP.left[i] right[i]分别表示往左边和往右边可以扩展多少

def largestRectangleArea(self, heights):
        """
        :type heights: List[int]
        :rtype: int
        """
        if not heights:
            return 0
        n = len(heights)
        left = [0] * n # 高度扩张的最左边
        right = [0] * n # 高度扩张的最右边
        for i in xrange(1, n):
            index = i - 1
            while index >= 0 and heights[index] >= heights[i]:
                index = left[index] - 1
            left[i] = index + 1
        right[-1] = n - 1
        res = (right[-1] - left[-1] + 1) * heights[-1]
        for i in xrange(n - 1, -1, -1):
            index = i + 1
            while index < n and heights[index] >= heights[i]:
                index = right[index] + 1
            right[i] = index - 1
            res = max(res, (right[i] - left[i] + 1) * heights[i])
        return res
View Code

85.Maximal Rectangle

Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle containing only 1's and return its area.

For example, given the following matrix:

1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0
Return 6.

当然,第一种思路可以考虑以每一行为底的最大矩形,就相当于做了n次的Largest Rectangle in Histogram,用左右扩的方法的话最坏的时间复杂度是O(n * m ^ 2),用递增栈的话最坏的时间复杂度是O(n * m)

这里不直接的转化为一维,而是直接操作。引入一个curLeft记录当前往左扩和当前往右扩,最后时间复杂度优化到O(n * m)

def maximalRectangle(self, matrix):
        """
        :type matrix: List[List[str]]
        :rtype: int
        """
        if not matrix:
            return 0
        m = len(matrix)
        n = len(matrix[0])
        heights = [0] * n
        left = [0] * n
        right = [n] * n
        res = 0
        for i in xrange(m):
            curLeft = 0
            curRight = n
            for j in xrange(n):
                if matrix[i][j] == '1':
                    heights[j] += 1
                    left[j] = max(left[j], curLeft)
                else:
                    heights[j] = 0
                    left[j] = 0
                    curLeft = j + 1
            for j in xrange(n - 1, -1, -1):
                if matrix[i][j] == '1':
                    right[j] = min(right[j], curRight)
                    res = max(res, (right[j] - left[j]) * heights[j])
                else:
                    right[j] = n
                    curRight = j
        return res
View Code

 86.Partition List

Given a linked list and a value x, partition it such that all nodes less than x come before nodes greater than or equal to x.

You should preserve the original relative order of the nodes in each of the two partitions.

For example,
Given 1->4->3->2->5->2 and x = 3,
return 1->2->2->4->3->5.

dummySmall

dummyBigger

tailSmall

tailBigger

需要注意的是最后把tailBigger.next = None

def partition(self, head, x):
        """
        :type head: ListNode
        :type x: int
        :rtype: ListNode
        """
        if not head:
            return head
        dummySmall = ListNode(0)
        tailSmall = dummySmall
        dummyBigger = ListNode(0)
        tailBigger = dummyBigger
        while head:
            if head.val < x:
                tailSmall.next = head
                tailSmall = head
                head = head.next
            else:
                tailBigger.next = head
                tailBigger = head
                head = head.next
        tailSmall.next = dummyBigger.next
        tailBigger.next = None #Attention!
        return dummySmall.next
View Code

87.Scramble String

Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrings recursively.

Below is one possible representation of s1 = "great":

    great
   /    
  gr    eat
 /     /  
g   r  e   at
           / 
          a   t
To scramble the string, we may choose any non-leaf node and swap its two children.

For example, if we choose the node "gr" and swap its two children, it produces a scrambled string "rgeat".

    rgeat
   /    
  rg    eat
 /     /  
r   g  e   at
           / 
          a   t
We say that "rgeat" is a scrambled string of "great".

Similarly, if we continue to swap the children of nodes "eat" and "at", it produces a scrambled string "rgtae".

    rgtae
   /    
  rg    tae
 /     /  
r   g  ta  e
       / 
      t   a
We say that "rgtae" is a scrambled string of "great".

Given two strings s1 and s2 of the same length, determine if s2 is a scrambled string of s1.

递归。检测字符出现的是不是一样,然后左右取,左右等去判断

def isScramble(self, s1, s2):
        """
        :type s1: str
        :type s2: str
        :rtype: bool
        """
        if s1 == s2:
            return True
        if not s1 or not s2:
            return False
        m = len(s1)
        n = len(s2)
        if m != n:
            return False
        map = [0] * 128
        for c in s1:
            map[ord(c)] += 1
        for c in s2:
            if map[ord(c)] == 0:
                return False
            map[ord(c)] -= 1
        for i in range(1, m):
            if self.isScramble(s1[i:], s2[i:]) and self.isScramble(s1[:i], s2[:i]):
                return True
            if self.isScramble(s1[i:], s2[:n - i]) and self.isScramble(s1[:i], s2[n - i:]):
                return True
        return False
View Code

 88.Merge Sorted Array

Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array.

Note:
You may assume that nums1 has enough space (size that is greater or equal to m + n) to hold additional elements from nums2. The number of elements initialized in nums1 and nums2 are m and n respectively.

三个指针控制移动即可。

def merge(self, nums1, m, nums2, n):
        """
        :type nums1: List[int]
        :type m: int
        :type nums2: List[int]
        :type n: int
        :rtype: void Do not return anything, modify nums1 in-place instead.
        """
        index = m + n - 1
        m -= 1
        n -= 1
        while m >= 0 and n >= 0:
            if nums1[m] > nums2[n]:
                nums1[index] = nums1[m]
                m -= 1
                index -= 1
            else:
                nums1[index]= nums2[n]
                n -= 1
                index -= 1
        while n >= 0:
            nums1[index] = nums2[n]
            index -= 1
            n -= 1
View Code

89.Gray Code

The gray code is a binary numeral system where two successive values differ in only one bit.

Given a non-negative integer n representing the total number of bits in the code, print the sequence of gray code. A gray code sequence must begin with 0.

For example, given n = 2, return [0,1,3,2]. Its gray code sequence is:

00 - 0
01 - 1
11 - 3
10 - 2

n + 1是n的数,再加上n的数的倒序加上当前增长值

 def grayCode(self, n):
        """
        :type n: int
        :rtype: List[int]
        """
        if n <= 0:
            return [0]
        res = [0, 1]
        temp = 2
        for i in xrange(1, n):
            size = len(res)
            for j in xrange(size - 1, -1, -1):
                res.append(res[j] + temp)
            temp *= 2
        return res
View Code

90.Subsets II

Given a collection of integers that might contain duplicates, nums, return all possible subsets.

Note: The solution set must not contain duplicate subsets.

For example,
If nums = [1,2,2], a solution is:

[
  [2],
  [1],
  [1,2,2],
  [2,2],
  [1,2],
  []
]

DFS

def subsetsWithDup(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        res = []
        if not nums:
            return res
        nums.sort()
        self.dfs(nums, res, [], 0)
        return res
    def dfs(self, nums, res, cur, index):
        res.append(cur[:])
        n = len(nums)
        for i in xrange(index, n):
            if i != index and nums[i] == nums[i - 1]:
                continue
            cur.append(nums[i])
            self.dfs(nums, res, cur, i + 1)
            cur.pop()
View Code

91.Decode Ways --- not nug free

A message containing letters from A-Z is being encoded to numbers using the following mapping:

'A' -> 1
'B' -> 2
...
'Z' -> 26
Given an encoded message containing digits, determine the total number of ways to decode it.

For example,
Given encoded message "12", it could be decoded as "AB" (1 2) or "L" (12).

The number of ways decoding "12" is 2.

dp[i]表示必须以i结尾的译码方案数

遍历原字符串,首先以s[i- 1]是否为‘0’划分,为‘0’的很简单;不为‘0’的话,获取前一位结合的数num,分num>26与否,大于26很简单,小于的话,以s[i]是否为‘0’来划分。

 def numDecodings(self, s):
        """
        :type s: str
        :rtype: int
        """
        if not s:
            return 0
        if s[0] == '0':
            return 0
        n = len(s)
        dp = [0] * n
        dp[0] = 1
        for i in xrange(1, n):
            if s[i - 1] == '0':
                if s[i] == '0':
                    return 0
                else:
                    dp[i] = dp[i - 1]
            else:
                num = int(s[i - 1]) * 10 + int(s[i])
                if num > 26:
                    if s[i] == '0':
                        return 0
                    else:
                        dp[i] = dp[i - 1]
                else:
                    if s[i] == '0':
                        dp[i] = dp[i - 2] if i >= 2 else 1
                    else:
                        dp[i] = dp[i - 1] + dp[i - 2] if i >= 2 else 2
        return dp[-1]
View Code

 92.Reverse Linked List II

Reverse a linked list from position m to n. Do it in-place and in one-pass.

For example:
Given 1->2->3->4->5->NULL, m = 2 and n = 4,

return 1->4->3->2->5->NULL.

Note:
Given m, n satisfy the following condition:
1 ≤ m ≤ n ≤ length of list.

首先找到第m个结点的上一个结点prev,然后prev1.next = 后边的逆序,逆序部分也要和后边接上。

def reverseBetween(self, head, m, n):
        """
        :type head: ListNode
        :type m: int
        :type n: int
        :rtype: ListNode
        """
        if not head:
            return head
        dummyHead = ListNode(0)
        dummyHead.next = head
        prev1 = dummyHead
        for i in xrange(1, m):
            # if not prev1:
            #     return None
            prev1= prev1.next
        prev1.next = self.reverse(prev1.next, m, n)
        return dummyHead.next
    def reverse(self, head, m, n):
        temp1 = head
        prev = None
        n += 1
        for i in xrange(m, n):
            # if not head:
            #     return None
            temp = head.next
            head.next = prev
            prev = head
            head = temp
        temp1.next = head
        return prev
View Code

93.Restore IP Addresses --- not nug free

Given a string containing only digits, restore it by returning all possible valid IP address combinations.

For example:
Given "25525511135",

return ["255.255.11.135", "255.255.111.35"]. (Order does not matter)

backtracking.

start记录ip的这一位的开始点,然后遍历其往后的三为看可不可以构成一个0-255的数,深搜下去。

注意python的 if else 三目运算语句的优先级比算数运算符优先级高。

 def restoreIpAddresses(self, s):
        """
        :type s: str
        :rtype: List[str]
        """
        if not s or len(s) < 4 or len(s) > 12:
            return []
        res = []
        self.dfs(s, res, 0, 0, '')
        return res
    def dfs(self, s, res, start, count, ip):
        if count > 4:
            return
        if count == 4 and start == len(s):
            res.append(ip[:])
            return
        for i in xrange(1, 4):
            if start + i > len(s):
                break
            temp = s[start:start + i]
            if temp[0] == '0' and i != 1:
                break
            if i == 3 and int(temp) > 255:
                break
            self.dfs(s, res, start + i, count + 1, ip + temp + ('' if count == 3 else '.'))
View Code

94.Binary Tree Inorder Traversal

递归:

def inorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        res = []
        self.inorderTraverse(root, res)
        return res
    def inorderTraverse(self, root, res):
        if not root:
            return
        self.inorderTraverse(root.left, res)
        res.append(root.val)
        self.inorderTraverse(root.right, res)
View Code

非递归:

def inorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        res = []
        if not root:
            return res
        stack = []
        while stack or root:
            while root:
                stack.append(root)
                root = root.left
            root = stack.pop()
            res.append(root.val)
            root = root.right
        return res
View Code

95.Unique Binary Search Trees II --- not nug free

Given an integer n, generate all structurally unique BST's (binary search trees) that store values 1...n.

For example,
Given n = 3, your program should return all 5 unique BST's shown below.

   1         3     3      2      1
           /     /      /       
     3     2     1      1   3      2
    /     /                        
   2     1         2                 3

分治。分治程序求解[start, end]的所有树,可以以这区间的任何一个为根节点,左右分治。注意代码中Attention!

def generateTrees(self, n):
        """
        :type n: int
        :rtype: List[TreeNode]
        """
        if n < 1:
            return []
        return self.help(1, n)
    def help(self, start, end):
        res = []
        if start > end:
            res.append(None) #Attention!
            return res
        if start == end:
            res.append(TreeNode(start))
            return res
        for i in xrange(start, end + 1):
            left = self.help(start, i - 1)
            right = self.help(i + 1, end)
            for l in left:
                for r in right:
                    root = TreeNode(i) # Attnetion!
                    root.left = l
                    root.right = r
                    res.append(root)
        return res
View Code

dp。方法一中涉及许多重复计算,所以这里使用dp。dp[i]表示[1,i]的所有树

def generateTrees(self, n):
        """
        :type n: int
        :rtype: List[TreeNode]
        """
        if n < 1:
            return []
        dp = []
        dp.append([])
        dp[0].append(None)
        for i in xrange(1, (n + 1)):
            dp.append([])
            for j in xrange(i):
                left = dp[j]
                right = dp[i - j - 1]
                for l in left:
                    for r in right:
                        root = TreeNode(j + 1)
                        root.left = l
                        root.right = self.clone(r, j + 1)
                        dp[i].append(root)
        return dp[n]
    def clone(self, root, num):
        if not root:
            return None
        newRoot = TreeNode(root.val + num)
        newRoot.left = self.clone(root.left, num)
        newRoot.right = self.clone(root.right, num)
        return newRoot
View Code

 96. Unique Binary Search Trees

Given n, how many structurally unique BST's (binary search trees) that store values 1...n?

For example,
Given n = 3, there are a total of 5 unique BST's.

   1         3     3      2      1
           /     /      /       
     3     2     1      1   3      2
    /     /                        
   2     1         2                 3

dp.dp[i]表示[1, i]的方案数。

def numTrees(self, n):
        """
        :type n: int
        :rtype: int
        """
        if n < 1:
            return 0
        dp = [0] * (n + 1)
        dp[0] = 1
        for i in xrange(1, n + 1):
            for j in xrange(i):
                dp[i] += dp[j] * dp[i - 1 - j]
        return dp[n]
View Code

97.Interleaving String

Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2.

For example,
Given:
s1 = "aabcc",
s2 = "dbbca",

When s3 = "aadbbcbcac", return true.
When s3 = "aadbbbaccc", return false.

dp.dp[i][j]表示s1的前i个字符,s2的前j个字符是否能够与s3的前i + j个字符匹配

def isInterleave(self, s1, s2, s3):
        """
        :type s1: str
        :type s2: str
        :type s3: str
        :rtype: bool
        """
        m = len(s1)
        n = len(s2)
        if m + n != len(s3):
            return False
        dp = [[False for j in xrange(n + 1)] for i in xrange(m + 1)] # dp[i][j]表示s1的前i个字符,s2的前j个字符是否能够与s3的前i + j个字符匹配
        dp[0][0] = True
        for j in xrange(1, (n + 1)):
            if s2[j - 1] == s3[j - 1]:
                dp[0][j] = True
            else:
                break
        for i in xrange(1, (m + 1)):
            if (s1[i - 1] == s3[i - 1]):
                dp[i][0] = True
            else:
                break
        for i in xrange(1, (m + 1)):
            for j in xrange(1, (n + 1)):
                if s1[i - 1] == s3[i + j - 1]:
                    dp[i][j] |= dp[i - 1][j]
                if s2[j - 1] == s3[i + j - 1]:
                    dp[i][j] |= dp[i][j - 1]
        return dp[m][n]
View Code

98.Validate Binary Search Tree

Given a binary tree, determine if it is a valid binary search tree (BST).

Assume a BST is defined as follows:

The left subtree of a node contains only nodes with keys less than the node's key.
The right subtree of a node contains only nodes with keys greater than the node's key.
Both the left and right subtrees must also be binary search trees.
Example 1:
    2
   / 
  1   3
Binary tree [2,1,3], return true.
Example 2:
    1
   / 
  2   3
Binary tree [1,2,3], return false.

递归。递归程序控制一个最大值和最小值,注意最开始的这个最大值和最小值的初始化问题。

def isValidBST(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        return self.help(root, (1 << 31), (-1 << 31) - 1)
    def help(self, root, maxNum, minNum):
        if not root:
            return True
        if minNum < root.val < maxNum:
            return self.help(root.left, root.val, minNum) and self.help(root.right, maxNum, root.val) 
        else:
            return False
View Code

 99.Recover Binary Search Tree

wo elements of a binary search tree (BST) are swapped by mistake.

Recover the tree without changing its structure.

Note:
A solution using O(n) space is pretty straight forward. Could you devise a constant space solution?

中序遍历变形。找到prev.val > root.val的。

非递归:

def recoverTree(self, root):
        """
        :type root: TreeNode
        :rtype: void Do not return anything, modify root in-place instead.
        """
        first = None
        second = None
        prev = None
        stack = []
        while stack or root:
            while root:
                stack.append(root)
                root = root.left
            root = stack.pop()
            if prev and prev.val > root.val:
                if first:
                    second = root
                    break
                else:
                    first = prev
                    second = root
            prev = root
            root = root.right
        if first:
            temp = first.val
            first.val = second.val
            second.val = temp
View Code

递归:

first = None
    second = None
    prev = None
    def recoverTree(self, root):
        """
        :type root: TreeNode
        :rtype: void Do not return anything, modify root in-place instead.
        """
        global first
        global second
        self.inorderHelp(root)
        if self.first:
            temp = self.first.val
            self.first.val = self.second.val
            self.second.val = temp
    def inorderHelp(self, root):
        global first
        global second
        global prev
        if not root:
            return
        self.inorderHelp(root.left)
        if self.prev and self.prev.val > root.val:
            if self.first:
                self.second = root
                return
            else:
                self.first = self.prev
                self.second = root
        self.prev = root
        self.inorderHelp(root.right)
View Code

 100.Same Tree

Given two binary trees, write a function to check if they are equal or not.

Two binary trees are considered equal if they are structurally identical and the nodes have the same value.

 分治。

def isSameTree(self, p, q):
        """
        :type p: TreeNode
        :type q: TreeNode
        :rtype: bool
        """
        if not p and not q:
            return True
        if not p:
            return False
        if not q:
            return False
        if p.val != q.val:
            return False
        return self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right)
View Code

101.Symmetric Tree

Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center).

For example, this binary tree [1,2,2,3,4,4,3] is symmetric:

    1
   / 
  2   2
 /  / 
3  4 4  3
But the following [1,2,2,null,3,null,3] is not:
    1
   / 
  2   2
      
   3    3  

分治。

def isSymmetric(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        if not root:
            return True
        return self.isSame(root.left, root.right)
    def isSame(self, root1, root2):
        if not root1 and not root2:
            return True
        if not root1 or not root2:
            return False
        if root1.val != root2.val:
            return False
        return self.isSame(root1.left, root2.right) and self.isSame(root1.right, root2.left)
View Code

102.Binary Tree Level Order Traversal

Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, level by level).

For example:
Given binary tree [3,9,20,null,null,15,7],
    3
   / 
  9  20
    /  
   15   7
return its level order traversal as:
[
  [3],
  [9,20],
  [15,7]
]

队列。

def levelOrder(self, root):
        """
        :type root: TreeNode
        :rtype: List[List[int]]
        """
        res = []
        if not root:
            return res
        queue = []
        queue.append(root)
        while queue:
            size = len(queue)
            cur = []
            for i in xrange(size):
                root = queue.pop(0)
                cur.append(root.val)
                if root.left:
                    queue.append(root.left)
                if root.right:
                    queue.append(root.right)
            res.append(cur[:])
        return res
View Code

103.Binary Tree Zigzag Level Order Traversal

Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from left to right, then right to left for the next level and alternate between).

For example:
Given binary tree [3,9,20,null,null,15,7],
    3
   / 
  9  20
    /  
   15   7
return its zigzag level order traversal as:
[
  [3],
  [20,9],
  [15,7]
]

Z字形遍历。flag记录。队列

def zigzagLevelOrder(self, root):
        """
        :type root: TreeNode
        :rtype: List[List[int]]
        """
        res = []
        if not root:
            return res
        queue = []
        queue.append(root)
        flag = True
        while queue:
            size = len(queue)
            cur = []
            for i in xrange(size):
                root = queue.pop(0)
                if flag:
                    cur.append(root.val)
                else:
                    cur.insert(0, root.val)
                if root.left:
                    queue.append(root.left)
                if  root.right:
                    queue.append(root.right)
            flag = not flag
            res.append(cur[:])
        return res
View Code

 104.Maximum Depth of Binary Tree

Given a binary tree, find its maximum depth.

The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node.

分治。

def maxDepth(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        if not root:
            return 0
        return 1 + max(self.maxDepth(root.left), self.maxDepth(root.right))
View Code

105.Construct Binary Tree from Preorder and Inorder Traversal

Given preorder and inorder traversal of a tree, construct the binary tree.  

分治。

def buildTree(self, preorder, inorder):
        """
        :type preorder: List[int]
        :type inorder: List[int]
        :rtype: TreeNode
        """
        if not preorder or not inorder or not len(preorder) == len(inorder):
            return None
        map = {}
        n = len(preorder)
        for i in xrange(n):
            map[inorder[i]] = i    
        return self.help(preorder, inorder, 0, len(preorder) - 1, 0, len(inorder) - 1, map)
    def help(self, preorder, inorder, prestart, preend, instart, inend, map):
        if prestart > preend:
            return None
        if prestart == preend:
            return TreeNode(preorder[prestart])
        root = TreeNode(preorder[prestart])
        index = map[preorder[prestart]]
        root.left = self.help(preorder, inorder, prestart + 1, index - instart + prestart, instart, index - 1, map)
        root.right = self.help(preorder, inorder, index - instart + prestart + 1, preend, index + 1, inend, map)
        return root
View Code

 106.Construct Binary Tree from Inorder and Postorder Traversal

Given inorder and postorder traversal of a tree, construct the binary tree.  

分治。

def buildTree(self, inorder, postorder):
        """
        :type inorder: List[int]
        :type postorder: List[int]
        :rtype: TreeNode
        """
        if not inorder or not postorder:
            return None
        if len(inorder) != len(postorder):
            return None
        map = {}
        n = len(inorder)
        for i in xrange(n):
            map[inorder[i]] = i
        return self.help(inorder, 0, n - 1, postorder, 0, n - 1, map)
    def help(self, inorder, instart, inend, postorder, poststart, postend, map):
        if instart > inend:
            return None
        if instart == inend:
            return TreeNode(inorder[instart])
        root = TreeNode(postorder[postend])
        index = map[postorder[postend]]
        root.left = self.help(inorder, instart, index - 1, postorder, poststart, poststart + index - instart - 1, map)
        root.right = self.help(inorder, index + 1, inend, postorder, poststart + index - instart, postend - 1, map)
        return root
View Code

107.Binary Tree Level Order Traversal II

Given a binary tree, return the bottom-up level order traversal of its nodes' values. (ie, from left to right, level by level from leaf to root).

For example:
Given binary tree [3,9,20,null,null,15,7],
    3
   / 
  9  20
    /  
   15   7
return its bottom-up level order traversal as:
[
  [15,7],
  [9,20],
  [3]
]

层序遍历。

def levelOrderBottom(self, root):
        """
        :type root: TreeNode
        :rtype: List[List[int]]
        """
        res = []
        if not root:
            return res
        queue = []
        queue.append(root)
        while queue:
            size = len(queue)
            cur = []
            for i in xrange(size):
                root = queue.pop(0)
                cur.append(root.val)
                if root.left:
                    queue.append(root.left)
                if root.right:
                    queue.append(root.right)
            res.insert(0, cur[:])
        return res
View Code

108.Convert Sorted Array to Binary Search Tree

Given an array where elements are sorted in ascending order, convert it to a height balanced BST.  

分治。

def sortedArrayToBST(self, nums):
        """
        :type nums: List[int]
        :rtype: TreeNode
        """
        if not nums:
            return None
        return self.help(nums, 0, len(nums) - 1)
    def help(self, nums, start, end):
        if start > end:
            return None
        if start == end:
            return TreeNode(nums[start])
        mid = (start + end) / 2
        root = TreeNode(nums[mid])
        root.left = self.help(nums, start, mid - 1)
        root.right = self.help(nums, mid + 1, end)
        return root
View Code

109.Convert Sorted List to Binary Search Tree --- not bug free

Given a singly linked list where elements are sorted in ascending order, convert it to a height balanced BST.  

首先求出节点个数,start, end控制递归。外部使用temp控制遍历到哪儿了。

temp = None
    def sortedListToBST(self, head):
        """
        :type head: ListNode
        :rtype: TreeNode
        """
        if not head:
            return None
        global temp
        self.temp = head
        n = 0
        cur = head
        while cur:
            n += 1
            cur = cur.next
        return self.help(0, n - 1)
    def help(self, start, end):
        if start > end:
            return None
        if start == end:
            val = self.temp.val
            self.temp = self.temp.next
            return TreeNode(val)
        mid = (start + end) / 2
        global temp
        left = self.help(start, mid - 1)
        root = TreeNode(self.temp.val)
        self.temp = self.temp.next
        right = self.help(mid + 1, end)
        root.left = left
        root.right = right
        return root
View Code

 110.Balanced Binary Tree

Given a binary tree, determine if it is height-balanced.

For this problem, a height-balanced binary tree is defined as a binary tree in which the depth of the two subtrees of every node never differ by more than 1. 

分治。-1 表示不平衡。

def isBalanced(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        if not root:
            return True
        return not self.height(root) == -1
    def height(self, root):
        if not root:
            return 0
        left = self.height(root.left)
        right = self.height(root.right)
        if left == -1 or right == -1:
            return -1
        if abs(left - right) > 1:
            return -1
        return max(left, right) + 1
View Code

 111.Minimum Depth of Binary Tree

Given a binary tree, find its minimum depth.

The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node.

层序遍历。

def minDepth(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        if not root:
            return 0
        queue = []
        queue.append(root)
        res = 1
        while queue:
            size = len(queue)
            for i in xrange(size):
                cur = queue.pop(0)
                if not cur.left and not cur.right:
                    return res
                if cur.left:
                    queue.append(cur.left)
                if cur.right:
                    queue.append(cur.right)
            res += 1
        return res
View Code

 112.Path Sum ---not bug free

Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the values along the path equals the given sum.

For example:
Given the below binary tree and sum = 22,
              5
             / 
            4   8
           /   / 
          11  13  4
         /        
        7    2      1
return true, as there exist a root-to-leaf path 5->4->11->2 which sum is 22.  

有个坑,不好描述的坑,仔细思考。

def hasPathSum(self, root, sum):
        """
        :type root: TreeNode
        :type sum: int
        :rtype: bool
        """
        return self.help(root, sum)
    def help(self, root, target):
        if not root:
            return False
        if not root.left and not root.right: 
            if target == root.val:
                return True
            else:
                return False
        return self.help(root.left, target - root.val) or self.help(root.right, target - root.val)
View Code

113.Path Sum II

Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given sum.

For example:
Given the below binary tree and sum = 22,
              5
             / 
            4   8
           /   / 
          11  13  4
         /      / 
        7    2  5   1
return
[
   [5,4,11,2],
   [5,8,4,5]
]

 backtracking.注意cur.pop()

def pathSum(self, root, sum):
        """
        :type root: TreeNode
        :type sum: int
        :rtype: List[List[int]]
        """
        res = []
        self.help(root, sum, res, [])
        return res
    def help(self, root, target, res, cur):
        if not root:
            return
        if not root.left and not root.right:
            if target == root.val:
                cur.append(root.val)
                res.append(cur[:])
                cur.pop()
            return
        else:
            cur.append(root.val)
            self.help(root.left, target - root.val, res, cur)
            self.help(root.right, target - root.val, res ,cur)
            cur.pop()
View Code

 114.Flatten Binary Tree to Linked List

Given a binary tree, flatten it to a linked list in-place.

For example,
Given

         1
        / 
       2   5
      /    
     3   4   6
The flattened tree should look like:
   1
    
     2
      
       3
        
         4
          
           5
            
             6  

先序遍历。每次节点任务完成后,更新左右节点。注意左二子为None的更新。右儿子为栈顶。

def flatten(self, root):
        """
        :type root: TreeNode
        :rtype: void Do not return anything, modify root in-place instead.
        """
        if not root:
            return root
        stack = []
        stack.append(root)
        while stack:
            root = stack.pop()
            if root.right:
                stack.append(root.right)
            if root.left:
                stack.append(root.left)
            root.left = None # Attention!
            if stack:
                root.right = stack[-1]
View Code

115.Distinct Subsequences --- not bug free

Given a string S and a string T, count the number of distinct subsequences of T in S.

A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, "ACE" is a subsequence of "ABCDE" while "AEC" is not).

Here is an example:
S = "rabbbit", T = "rabbit"

Return 3.

dp.dp[i][j]表示s前i个字符的字串和t前j个字符的字串,有多少种方案。

考虑s[i - 1]是否等于t[j - 1],这会影响是否使用s的当前字符s[i - 1].

def numDistinct(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: int
        """
        if s == None or t == None:
            return 0
        if len(s) < len(t):
            return 0
        m = len(s)
        n = len(t)
        dp = [[0 for i in xrange(n + 1)] for j in xrange(m + 1)]
        for i in xrange(m + 1):
            dp[i][0] = 1
        for i in xrange(1, m + 1):
            for j in xrange(1, n + 1):
                if s[i - 1] == t[j - 1]:
                    dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j]
                else:
                    dp[i][j] = dp[i - 1][j]
        return dp[m][n]
View Code

 116.Populating Next Right Pointers in Each Node

 

Given a binary tree

    struct TreeLinkNode {
      TreeLinkNode *left;
      TreeLinkNode *right;
      TreeLinkNode *next;
    }
Populate each next pointer to point to its next right node. If there is no next right node, the next pointer should be set to NULL.

Initially, all next pointers are set to NULL.

Note:

You may only use constant extra space.
You may assume that it is a perfect binary tree (ie, all leaves are at the same level, and every parent has two children).
For example,
Given the following perfect binary tree,
         1
       /  
      2    3
     /   / 
    4  5  6  7
After calling your function, the tree should look like:
         1 -> NULL
       /  
      2 -> 3 -> NULL
     /   / 
    4->5->6->7 -> NULL  

层序遍历。

def connect(self, root):
        if not root:
            return
        queue = []
        queue.append(root)
        while queue:
            size = len(queue)
            for i in xrange(size):
                cur = queue.pop(0)
                cur.next = queue[0] if i != size - 1 else None
                if cur.left:
                    queue.append(cur.left)
                if cur.right:
                    queue.append(cur.right)
View Code

父亲层处理儿子层的下一节点。也是一层一层的遍历。

 1 def connect(self, root):
 2         if not root:
 3             return
 4         while root.left:
 5             cur = root
 6             while cur:
 7                 cur.left.next = cur.right
 8                 if cur.next:
 9                     cur.right.next = cur.next.left
10                 cur = cur.next
11             root = root.left
View Code

117.Populating Next Right Pointers in Each Node II

Follow up for problem "Populating Next Right Pointers in Each Node".

What if the given tree could be any binary tree? Would your previous solution still work?

Note:

You may only use constant extra space.
For example,
Given the following binary tree,
         1
       /  
      2    3
     /     
    4   5    7
After calling your function, the tree should look like:
         1 -> NULL
       /  
      2 -> 3 -> NULL
     /     
    4-> 5 -> 7 -> NULL  

并不是完全二叉树,则上述方法二不适用,层序遍历仍然有效。

def connect(self, root):
        if not root:
            return
        queue = []
        queue.append(root)
        while queue:
            size = len(queue)
            for i in xrange(size):
                cur = queue.pop(0)
                cur.next = queue[0] if i != size - 1 else None
                if cur.left:
                    queue.append(cur.left)
                if cur.right:
                    queue.append(cur.right)
View Code

 118.Pascal's Triangle

Given numRows, generate the first numRows of Pascal's triangle.

For example, given numRows = 5,
Return

[
     [1],
    [1,1],
   [1,2,1],
  [1,3,3,1],
 [1,4,6,4,1]
]  

从第二行开始,出去左右两边的,都等于上一行的相加。

def generate(self, numRows):
        """
        :type numRows: int
        :rtype: List[List[int]]
        """
        res = []
        if numRows < 1:
            return res
        res.append([1])
        for i in xrange(1, numRows):
            cur = [1]
            for j in xrange(i - 1):
                cur.append(res[i - 1][j] + res[i - 1][j + 1])
            cur.append(1)
            res.append(cur[:])
        return res
View Code

119.Pascal's Triangle II

Given an index k, return the kth row of the Pascal's triangle.

For example, given k = 3,
Return [1,3,3,1].

res 和 cur,由res求cur,求得cur之后更新res

def getRow(self, rowIndex):
        """
        :type rowIndex: int
        :rtype: List[int]
        """
        if rowIndex < 0:
            return []
        res = [1]
        for i in xrange(1, rowIndex + 1):
            cur = [1]
            for j in xrange(1, i):
                cur.append(res[j - 1] + res[j])
            cur.append(1)
            res = cur
        return res
View Code

 120.Triangle

Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below.

For example, given the following triangle
[
     [2],
    [3,4],
   [6,5,7],
  [4,1,8,3]
]
The minimum path sum from top to bottom is 11 (i.e., 2 + 3 + 5 + 1 = 11). 

自底向上的DP.

def minimumTotal(self, triangle):
        """
        :type triangle: List[List[int]]
        :rtype: int
        """
        if not triangle:
            return 0
        m = len(triangle)
        dp = [[0 for i in  xrange(m)] for j in xrange(m)]
        for j in xrange(m):
            dp[m - 1][j] = triangle[m - 1][j]
        for i in xrange(m - 2, -1, -1):
            for j in xrange(i + 1):
                dp[i][j] = min(dp[i + 1][j], dp[i + 1][j + 1]) + triangle[i][j]
        return dp[0][0]
View Code

121.Best Time to Buy and Sell Stock

Say you have an array for which the ith element is the price of a given stock on day i.

If you were only permitted to complete at most one transaction (ie, buy one and sell one share of the stock), design an algorithm to find the maximum profit.  

 记录最小值,比最小值小则更新最小值,否则计算收益更新res

def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        if not prices:
            return 0
        res = 0
        min = prices[0]
        n = len(prices)
        for i in xrange(1, n):
            if prices[i] < min:
                min = prices[i]
            else:
                res = max(res, prices[i] - min)
        return res
View Code

 122.Best Time to Buy and Sell Stock II

Say you have an array for which the ith element is the price of a given stock on day i.

Design an algorithm to find the maximum profit. You may complete as many transactions as you like (ie, buy one and sell one share of the stock multiple times). However, you may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).

 后一天价格比前一天高就加上差价。

 def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        if not prices:
            return 0
        res = 0
        n = len(prices)
        for i in xrange(1, n):
            if prices[i] > prices[i - 1]:
                res += prices[i] - prices[i - 1]
        return res
View Code

123.Best Time to Buy and Sell Stock III

Say you have an array for which the ith element is the price of a given stock on day i.
Design an algorithm to find the maximum profit. You may complete at most two transactions.

 dp.left[i]表示前i个一次交易的最大,right[i]表示后i个一次交易的最大。left[i] + right[i]更新res.

def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        if not prices:
            return 0
        n = len(prices)
        left = [0] * n
        right = [0] * n
        minNum = prices[0]
        for i in xrange(1, n):
            if prices[i] < minNum:
                left[i] = left[i - 1]
                minNum = prices[i]
            else:
                left[i] = max(left[i - 1], prices[i] - minNum)
        maxNum = prices[n - 1]
        res = left[n - 1]
        for i in xrange(n - 2, -1, -1):
            if prices[i] > maxNum:
                right[i] = right[i + 1]
                maxNum = prices[i]
            else:
                right[i] = max(right[i + 1], maxNum - prices[i])
            res = max(res, left[i] + right[i])
        return res
View Code

124.Binary Tree Maximum Path Sum

Given a binary tree, find the maximum path sum.

For this problem, a path is defined as any sequence of nodes from some starting node to any node in the tree along the parent-child connections. The path must contain at least one node and does not need to go through the root.

For example:
Given the below binary tree,

       1
      / 
     2   3
Return 6.

  递归。注意为None的时候的返回值。

class Solution(object):
    def maxPathSum(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        return self.help(root).any2any
    def help(self, root):
        if not root:
            return ResultType(-1 << 32, -1 << 32)
        left = self.help(root.left)
        right = self.help(root.right)
        root2any = max(max(0, left.root2any), max(0, right.root2any)) + root.val
        any2any = max(0, left.root2any) + max(0, right.root2any) + root.val
        any2any = max(any2any, left.any2any, right.any2any)
        return ResultType(root2any, any2any)
class ResultType(object):
    def __init__(self, root2any, any2any):
        self.root2any = root2any
        self.any2any = any2any
View Code

125.Valid Palindrome

Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases.

For example,
"A man, a plan, a canal: Panama" is a palindrome.
"race a car" is not a palindrome.

 两个指针。

def isPalindrome(self, s):
        """
        :type s: str
        :rtype: bool
        """
        if not s:
            return True
        left = 0
        right = len(s) - 1
        while left < right:
            while left < right and not s[left].isalnum():
                left += 1
            while left < right and not s[right].isalnum():
                right -= 1
            if s[left].lower() != s[right].lower() :
                return False
            left += 1
            right -= 1
        return True
View Code

 126.Word Ladder II --- not bug free

Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transformation sequence(s) from beginWord to endWord, such that:

Only one letter can be changed at a time
Each transformed word must exist in the word list. Note that beginWord is not a transformed word.
For example,

Given:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log","cog"]
Return
  [
    ["hit","hot","dot","dog","cog"],
    ["hit","hot","lot","log","cog"]
  ]
Note:
Return an empty list if there is no such transformation sequence.
All words have the same length.
All words contain only lowercase alphabetic characters.
You may assume no duplicates in the word list.
You may assume beginWord and endWord are non-empty and are not the same.

  这个题花了好长时间才ac。主要原因:1.题目要求和之前的不同了,wordList中必须包含endWord;2.python中字典如果不包含key,去获取key的value的时候是会报错的,而java中不会报错,会得到null。所以java中去获取之后看为不为null返回,python中需要去看包不包含这个key。

解题思路:

1.首先是需要获取adjMap.具体做法是去除每一个位置的那个字母得到rep,把相同rep的放到一个list中,然后list中两两互为adj

2.然后需要获取previousMap,由于需要找所有最短路径,所以需要使用记录具体的distanceMap。使用一个queue实现

3.然后回溯即可。

def findLadders(self, beginWord, endWord, wordList):
        """
        :type beginWord: str
        :type endWord: str
        :type wordList: List[str]
        :rtype: List[List[str]]
        """
        if not beginWord or not endWord or not wordList:
            return []
        adjMap = {}
        wordList = set(wordList)
        if endWord not in wordList:
            return []
        wordList.add(beginWord)
        self.getAdjMap(wordList, adjMap, len(beginWord))
        # print adjMap
        previousMap = self.getPreviousMap(adjMap, beginWord, endWord)
        # print previousMap
        res = []
        cur = [endWord]
        self.dfs(previousMap, beginWord, endWord, res, cur)
        return res
    def dfs(self, previousMap, beginWord, endWord, res, cur):
        if beginWord == endWord:
            res.append(cur[:])
            return
        if endWord not in previousMap:
            return
        prevList = previousMap[endWord]
        for prev in prevList:
            cur.insert(0, prev)
            self.dfs(previousMap, beginWord, prev, res, cur)
            cur.pop(0)
    def getPreviousMap(self, adjMap, beginWord, endWord):
        previousMap = {}
        distanceMap = {}
        previousMap[beginWord] = None
        distanceMap[beginWord] = 0
        queue = []
        queue.append(beginWord)
        while queue:
            word = queue.pop(0)
            if word not in  adjMap:
                continue
            adjList = adjMap[word]
            for adj in adjList:
                if  adj not in previousMap:
                    previousMap[adj] = [word]
                    distanceMap[adj] = distanceMap[word] + 1
                    queue.append(adj)
                elif distanceMap[word] + 1 == distanceMap[adj]:
                    previousMap[adj].append(word)
        return previousMap
    
    def getAdjMap(self, wordList, adjMap, n):
        for i in xrange(n):
            repToWord = {}
            for word in wordList:
                rep = word[0:i] + word[(i + 1) : n]
                self.update(rep, word, repToWord)
            for rep in repToWord:
                if len(repToWord[rep]) < 2:
                    continue
                list = repToWord[rep]
                for str1 in list:
                    for str2 in list:
                        if str1 != str2:
                            self.update(str1, str2, adjMap)
    def update(self, rep, word, repToWord):
        if not rep in repToWord:
            repToWord[rep] = []
        repToWord[rep].append(word)
View Code

 127.Word Ladder

Given two words (beginWord and endWord), and a dictionary's word list, find the length of shortest transformation sequence from beginWord to endWord, such that:

Only one letter can be changed at a time.
Each transformed word must exist in the word list. Note that beginWord is not a transformed word.
For example,

Given:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log","cog"]
As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog",
return its length 5.

Note:
Return 0 if there is no such transformation sequence.
All words have the same length.
All words contain only lowercase alphabetic characters.
You may assume no duplicates in the word list.
You may assume beginWord and endWord are non-empty and are not the same.

  和上题主要思路一样,只求最短路径,所以只需要找到一条路径即可,不在需要distanceMap,previousMap的value也不再是一个list。

def ladderLength(self, beginWord, endWord, wordList):
        """
        :type beginWord: str
        :type endWord: str
        :type wordList: List[str]
        :rtype: int
        """
        if not beginWord or not endWord or not wordList:
            return 0
        mset = set(wordList)
        if endWord not in mset:
            return 0
        mset.add(beginWord)
        adjMap = {}
        self.getAdjMap(mset, adjMap, len(beginWord))
        previousMap = self.getPreviousMap(beginWord, endWord, adjMap)
        return self.getLength(beginWord, endWord, previousMap)    
    def getPreviousMap(self, beginWord, endWord, adjMap):
        previousMap = {}
        previousMap[beginWord] = None
        queue = [beginWord]
        while queue:
            word = queue.pop(0)
            if word not in adjMap:
                continue
            list = adjMap[word]
            for str in list:
                if str in previousMap:
                    continue
                previousMap[str] = word
                queue.append(str)
                if str == endWord:
                    return previousMap
        return previousMap
    def getLength(self, beginWord, endWord, previousMap):
        length = 0
        while endWord:
            length += 1
            if endWord not in previousMap:
                return 0
            endWord = previousMap[endWord]
        return length
    def getAdjMap(self, wordList, adjMap, n):
        for i in xrange(n):
            repToWord = {}
            for word in wordList:
                rep = word[0 : i] + word[(i + 1) : n]
                self.update(rep, word, repToWord)
            for rep in repToWord.keys():
                list = repToWord.get(rep)
                if len(list) < 2:
                    continue
                for str1 in list:
                    for str2 in list:
                        if str1 != str2:
                            self.update(str1, str2, adjMap)
    def update(self, str1, str2, map):
        if str1 not in map:
            map[str1] = []
        map[str1].append(str2)
View Code

 128.Longest Consecutive Sequence --- not bug free

Total Accepted: 100920
Total Submissions: 278863
Difficulty: Hard
Contributor: LeetCode
Given an unsorted array of integers, find the length of the longest consecutive elements sequence.

For example,
Given [100, 4, 200, 1, 3, 2],
The longest consecutive elements sequence is [1, 2, 3, 4]. Return its length: 4.

Your algorithm should run in O(n) complexity.

  首先当然有一种很直观的想法就是排序之后遍历一边,但是这是O(nlogn)的复杂度,需要O(n)的复杂度的话,使用一个set,首先加入所有的元素,然后遍历原来的数组,对于每个数往两边扩展(如果在set中的话,注意扩展之后需要删除这个元素,以免后边又扩进去了。)

def longestConsecutive(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if not nums:
            return 0
        mset = set(nums)
        res = 0
        for num in nums:
            down = num - 1
            while down in mset:
                mset.remove(down)
                down -= 1
            up = num + 1
            while up in mset:
                mset.remove(up)
                up += 1
            res = max(res, up - down - 1)
        return res
View Code

129.Sum Root to Leaf Numbers

Total Accepted: 108165
Total Submissions: 300355
Difficulty: Medium
Contributor: LeetCode
Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a number.

An example is the root-to-leaf path 1->2->3 which represents the number 123.

Find the total sum of all root-to-leaf numbers.

For example,

    1
   / 
  2   3
The root-to-leaf path 1->2 represents the number 12.
The root-to-leaf path 1->3 represents the number 13.

Return the sum = 12 + 13 = 25.
View Code

 分治。

res = 0
    def sumNumbers(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        global res
        if not root:
            return 0
        self.help(root, root.val)
        return self.res
    def help(self, root, cur):
        global res
        if not root.left and not root.right:
            self.res += cur
        if root.left:
            self.help(root.left, cur * 10 + root.left.val)
        if root.right:
            self.help(root.right, cur * 10 + root.right.val)
View Code

 130.Surrounded Regions

Given a 2D board containing 'X' and 'O' (the letter O), capture all regions surrounded by 'X'.

A region is captured by flipping all 'O's into 'X's in that surrounded region.

For example,
X X X X
X O O X
X X O X
X O X X
After running your function, the board should be:

X X X X
X X X X
X X X X
X O X X
View Code

DFS。容易stack溢出,加了最后的if 判断

def solve(self, board):
        """
        :type board: List[List[str]]
        :rtype: void Do not return anything, modify board in-place instead.
        """
        if not board:
            return
        m = len(board)
        n = len(board[0])
        for i in range(m):
            self.dfs(board, i, 0)
            self.dfs(board, i , n - 1)
        for j in range(n):
            self.dfs(board, 0, j)
            self.dfs(board, m - 1, j)
        for i in range(m):
            for j in range(n):
                if board[i][j] == '1':
                    board[i][j] = 'O'
                else:
                    board[i][j] = 'X'
    def dfs(self, board, i, j):
        m = len(board)
        n = len(board[0])
        if i < 0 or i >= m or j < 0 or j >= n:
            return
        if board[i][j] != 'O':
            return
        board[i][j] = '1'
        self.dfs(board, i + 1, j)
        self.dfs(board, i - 1, j)
        self.dfs(board, i, j + 1)
        if j > 1:
            self.dfs(board, i, j - 1)    
View Code

 UnionFind。

class Solution(object):
    def solve(self, board):
        """
        :type board: List[List[str]]
        :rtype: void Do not return anything, modify board in-place instead.
        """
        if not board:
            return
        m = len(board)
        n = len(board[0])
        uf = UnionFind(m * n + 1)
        dummyNode = m * n
        for j in range(n):
            if board[0][j] == 'O':
                uf.union(self.node(0, j, n), dummyNode)
            if board[m - 1][j] == 'O':
                uf.union(self.node(m - 1, j, n), dummyNode)
        for i in range(m):
            if board[i][0] == 'O':
                uf.union(self.node(i, 0, n), dummyNode)
            if board[i][n - 1] == 'O':
                uf.union(self.node(i, n - 1, n), dummyNode)
        for i in range(1, m - 1):
            for j in range(1, n - 1):
                if board[i][j] != 'O':
                    continue
                if board[i - 1][j] == 'O':
                    uf.union(self.node(i - 1, j, n), self.node(i, j, n))
                if board[i + 1][j] == 'O':
                    uf.union(self.node(i + 1, j, n), self.node(i, j, n))
                if board[i][j - 1] == 'O':
                    uf.union(self.node(i, j - 1, n), self.node(i, j, n))
                if board[i][j + 1] == 'O':
                    uf.union(self.node(i, j + 1, n), self.node(i, j, n))
        for i in range(m):
            for j in range(n):
                if uf.find(self.node(i, j, n)) == uf.find(dummyNode):
                    board[i][j] = 'O'
                else:
                    board[i][j] = 'X'
    def node(self, i, j, n):
        return i * n + j;
class UnionFind(object):
    def __init__(self, n):
        self.count = n
        self.ids = [i for i in range(n)]
        self.sz = [1 for i in range(n)]
    def union(self, p, q):
        i = self.find(p)
        j = self.find(q)
        if i == j:
            return
        elif self.sz[i] < self.sz[j]:
            self.ids[i] = j
            self.sz[j] += self.sz[i]
            self.count -= 1
        else:
            self.ids[j] = i
            self.sz[i] += self.sz[j]
            self.count -= 1
    def find(self, p):
        while self.ids[p] != p:
            self.ids[p] = self.ids[self.ids[p]]
            p = self.ids[p]
        return p

    def count(self):
        return self.count
View Code

 

原文地址:https://www.cnblogs.com/futurehau/p/6564471.html