futurehau

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
统计
 

1.Two Sum

使用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

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

使用数组充当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

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

以每个点为中心扩张

复制代码
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

每一行用一个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

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

复制代码
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

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

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

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

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

复制代码
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

变换点为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

从后边开始遍历,以是否大于等于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

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

复制代码
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

排序之后两个指针控制移动。需要注意的是:找到一个满足条件之后,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

和上题大同小异

复制代码
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

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

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

两个指针控制,找到倒数第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

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

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

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

分治。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

搞清逻辑就行了。

复制代码
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

递归。找出前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

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

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()

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

复制代码
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

二分。

复制代码
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

两层循环,外层循环为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

找到第一个左边比我小的,然后右半部分逆序。如果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

主要是思想,实现很简单。动规: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

根据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

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

复制代码
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

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

  

 36.Valid Sudoku --- not bug free

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

复制代码
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

递归程序控制行,然后内部控制列。遇到 '.' 检测合适的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

就是按照规则来,一个一个的迭代。注意迭代过程中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

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

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

实现很简单,主要是思想:可能的结果为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

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

复制代码
 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

 

因子 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

一种思路可以求出一个数的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

方法一: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

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

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

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

复制代码
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

相同的放在一个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

二分。注意次方为 -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

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

复制代码
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

同样的道理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

前缀和为负则更新为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

从外到内,一层一层的添加。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

贪心算法。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

方法一:使用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

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

另外一种是二分。找到第一个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

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

复制代码
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

和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

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

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

首先求出链表长度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

方法一:二维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

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

复制代码
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

同理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

可能出现的字符有 数字 . 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

直接从后往前 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

从后开始,当前位为异或,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

遍历原来的字符串数组,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)

二分。

复制代码
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

复制代码
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

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

用第一行第一列来记录这行这列是否有"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

二分。

复制代码
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

两边两个指针控制,中间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

和第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

注意代码中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

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

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

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

允许重复了,那么其实最坏的复杂度就会达到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

有重复往后走,最后看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

现在允许重复的出现一次就更好办了。如果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

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

复制代码
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

当然,第一种思路可以考虑以每一行为底的最大矩形,就相当于做了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

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

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

复制代码
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

三个指针控制移动即可。

复制代码
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

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

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

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

首先找到第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

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

分治。分治程序求解[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

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

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

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

复制代码
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

中序遍历变形。找到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

 分治。

复制代码
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

分治。

复制代码
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

队列。

复制代码
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

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

分治。

复制代码
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

分治。

复制代码
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

分治。

复制代码
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

层序遍历。

复制代码
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

首先求出节点个数,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

分治。-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

层序遍历。

复制代码
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

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

复制代码
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

 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

先序遍历。每次节点任务完成后,更新左右节点。注意左二子为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

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

 

层序遍历。

复制代码
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

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

复制代码
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

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

复制代码
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

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

自底向上的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

 记录最小值,比最小值小则更新最小值,否则计算收益更新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

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

复制代码
 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

 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

  递归。注意为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

 两个指针。

复制代码
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

  这个题花了好长时间才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

  和上题主要思路一样,只求最短路径,所以只需要找到一条路径即可,不在需要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

  首先当然有一种很直观的想法就是排序之后遍历一边,但是这是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
复制代码

 

 

 

 

 

 

 

 

 

posted on   futurehau  阅读(629)  评论(0编辑  收藏  举报
编辑推荐:
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
阅读排行:
· ThreeJs-16智慧城市项目(重磅以及未来发展ai)
· .NET 原生驾驭 AI 新基建实战系列(一):向量数据库的应用与畅想
· Ai满嘴顺口溜,想考研?浪费我几个小时
· Browser-use 详细介绍&使用文档
· 软件产品开发中常见的10个问题及处理方法
 
点击右上角即可分享
微信分享提示