LeetCode

LeetCode 刷題隨手記 - 第一部分

前 256 題(非會(huì)員)犹菱,僅算法題煮纵,的吐槽

https://leetcode.com/problemset/algorithms/

說明

刷題指南

  • 不要背題色查,前面的基本題型需要熟悉
  • 不要刷太多題
  • 前面的基本題型需要熟悉
  • 記模版

背題很容易忘址貌,而且題目有具體的要求骂因,還總會(huì)有新的題目。
模板绍哎,比如大數(shù)来农、回溯、圖的深度優(yōu)先搜索崇堰、動(dòng)態(tài)規(guī)劃沃于。
一次刷一定量的題,方便類比和補(bǔ)遺海诲。對(duì)照課本上的知識(shí)點(diǎn)繁莹。
總之,為了解決題目特幔,不是單獨(dú)扯道理咨演。

關(guān)于 LeetCode

  • 是針對(duì)白板編程設(shè)計(jì)的題目

  • 手寫,

  • 測(cè)試

  • AC

  • LeetCode 的題目還都是基礎(chǔ)題蚯斯,白板編程的薄风,自己寫測(cè)試

  • AC 仍可能不對(duì)

  • 不 AC 不一定錯(cuò)饵较,比如 LeetCode 改題目了

  • AC

    • 對(duì)特殊值處理可能不對(duì)
    • 與題目中對(duì)實(shí)現(xiàn)方式的要求不一致
  • Leetcode 沒有對(duì)異常輸入的處理

  • 有些課本上的知識(shí)點(diǎn)目前的有沒有涵蓋到的

  • 而且僅算法題的涵蓋也有點(diǎn)窄

  • 不要在題目的范圍和已有的題目上限制

    • 其他方面的基礎(chǔ)知識(shí),未知的題目的分析方法

每道題選擇一個(gè)標(biāo)簽遭赂,為了按方法分類

  • 題后的標(biāo)簽用來按解法歸類
    • 只指定一個(gè)類別循诉,

比如 Array+DP 的

按題號(hào)排列,從學(xué)習(xí)的角度嵌牺,歸類更好打洼。

解答

使用 C/C++,按題號(hào)順序逆粹。

分類學(xué)習(xí)募疮。

1. Two Sum

  • 哈希表,O(N)
  • 或者先排序再查找僻弹,如果不是返回下標(biāo)

要點(diǎn)

  1. 數(shù)組遍歷:用 for 循環(huán)阿浓,可以求和,最大值蹋绽,最大值的下標(biāo)芭毙,元素是否存在。
  2. 雙指針:同向卸耘,可以兩頭退敦,可以嵌套◎伎梗可以快慢侈百,先后,收縮翰铡。
class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int,int> h;
        for(int i=0;;i++){
            int x = nums[i];
            if(h.count(x))
                return {h[x],i};
            h[target-x] = i;
        }
    }
};

2. Add Two Numbers

  • 鏈表钝域,遍歷和尾插
  • 大數(shù),加法

要點(diǎn)

  1. 大數(shù):用一個(gè)整數(shù)表示大數(shù)中一位(或幾位)锭魔,計(jì)算加法時(shí)產(chǎn)生進(jìn)位例证。
  2. 鏈表:和數(shù)組都是基礎(chǔ)的容器。鏈表是遞歸的結(jié)構(gòu)迷捧,可以遞歸遍歷织咧,尾遞歸寫成循環(huán)∧铮可以直接頭部插入或尾部插入(記錄最后節(jié)點(diǎn))烦感。為處理空鏈表方便,可以通過額外的頭節(jié)點(diǎn)膛堤。
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode* list = NULL;
        ListNode** p = &list;
        int s = 0;
        while(l1 || l2 || s){
            if(l1){
                s+ = l1->val;
                l1 = l1->next;
            }
            if(l2){
                s+ = l2->val;
                l2 = l2->next;
            }
            *p = new ListNode(s%10);
            p = &(*p)->next;
            s /= 10;
        }
        return list;
    }
};

3. Longest Substring Without Repeating Characters

  • 數(shù)組
  • 動(dòng)態(tài)規(guī)劃
  • O(N)

要點(diǎn)

  1. 雙指針:一個(gè)向前一步,另一個(gè)根據(jù)條件收縮晌该。該題在遍歷時(shí)記錄最大值肥荔。
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int y = 0;
        int b[128] = {0};
        int l = 0;
        for(int i=0;i<s.size();i++){
            char c = s[i];
            l = max(l,b[c]);
            y = max(y,i-l+1);
            b[c] = i+1;
        }
        return y;
    }
};
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int y = 0;
        vector<int> b(128, -1);
        int a = -1;
        for(int i=0;i<s.size();i++){
            char c = s[i];
            a = max(a,b[c]);
            y = max(y,i-a);
            b[c] = i;
        }
        return y;
    }
};

4. Median of Two Sorted Arrays

  • 雙數(shù)組的查找绿渣,找中位數(shù)。
  • 挺有趣的一道題燕耿!
  • 算總長(zhǎng)度中符,分奇偶
  • 轉(zhuǎn)化為求第 k 個(gè)值。
    • 從 0 開始是誉帅,從 1 開始淀散。
  • 有個(gè)相關(guān)的題

要點(diǎn)

  1. 雙有序數(shù)組:搜索時(shí),可以歸并為一個(gè)數(shù)組執(zhí)行查找蚜锨,也可以直接在雙數(shù)組上查找档插。
class Solution {
    double find(vector<int>& A, vector<int>& B, int k){
        int a = 0, b = 0;
        for(;;){
            if(k==0){
                if(!(b<B.size()) || (a<A.size() && A[a]<B[b]))
                    return A[a];
                else
                    return B[b];
            }
            int c = (k-1)/2;
            if(!(b+c<B.size()) || (a+c<A.size() && A[a+c]<=B[b+c])){
                a += c+1;
                k -= c+1;
            }else{
                b += c+1;
                k -= c+1;
            }
            
        }
    }
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int length = nums1.size() + nums2.size();
        if(length%2)
            return find(nums1,nums2,length/2);
        else
            return (find(nums1,nums2,length/2-1)+find(nums1,nums2,length/2))/2.0;
    }
};
double find(int* nums1, int nums1Size, int* nums2, int nums2Size, int k){
    for(;;){
        if(nums1Size>nums2Size){
            int* nums3 = nums2;
            nums2 = nums1;
            nums1 = nums3;
            nums1Size = nums1Size^nums2Size;
            nums2Size = nums1Size^nums2Size;
            nums1Size = nums1Size^nums2Size;
        }else if(nums1Size==0){
            return nums2[k-1];
        }else if(k==1){
            return nums1[0]<nums2[0] ? nums1[0] : nums2[0];
        }else{
            int k1 = k/2 < nums1Size ? k/2 : nums1Size;
            int k2 = k - k1;
            if(nums1[k1-1]==nums2[k2-1]){
                return nums1[k1-1];
            }else if(nums1[k1-1]<nums2[k2-1]){
                nums1 += k1;
                nums1Size -= k1;
                k -= k1;
            }else{
                nums2 += k2;
                nums2Size -= k2;
                k -= k2;
            }
        }
    }
}
double findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size) {
    int length = nums1Size + nums2Size;
    double med = find(nums1, nums1Size, nums2, nums2Size, length/2+1);
    if(length%2==0)
        med = (med+find(nums1, nums1Size, nums2, nums2Size, length/2))/2;
    return med;
}

5. Longest Palindromic Substring

  • 動(dòng)態(tài)規(guī)劃,后面回文子串的題目還會(huì)用到
    • 從前往后亚再,計(jì)算前綴郭膛,或者從后往前,計(jì)算后綴都可以
  • 這題也有別的更好的方法氛悬。
class Solution {
public:
    string longestPalindrome(string s) {
        int len = 0, start;
        int n = s.size();
        auto f = [&](int j, int k){
            while(j>=0 && k<n && s[j]==s[k]){
                j--, k++;
            }
            if(k-j-1>len){
                len = k-j-1;
                start = j+1;
            }
        };
        for(int i=0; i<n; i++){
            f(i, i);
            f(i, i+1);
        }
        return s.substr(start, len);
    }
};
class Solution {
public:
    string longestPalindrome(string s) {
        int len = 0, start;
        int n = s.size();
        bool d[n][n];
        memset(d, 0, sizeof(bool)*(n*n));
        for(int i=0; i<n; i++){
            for(int j=0;j<=i; j++){
                d[j][i] = s[j]==s[i] && (i-j<3 ||d[j+1][i-1]);
                if(d[j][i] && (i-j+1) > len){
                    len = i - j + 1;
                    start = j;
                }
                
            }
        }
        return s.substr(start, len);
    }
};

6. ZigZag Conversion

  • 存在下標(biāo)周期性映射關(guān)系
  • 分析 r=1,2,3,4,5 的情況
class Solution {
public:
    string convert(string s, int numRows) {
        if(numRows==1)
            return s;
        int d = 2*numRows-2;
        string y;
        for(int i=0; i<numRows; i++){
            for(int j=i; j<s.size(); j+=d){
                y.push_back(s[j]);
                if(i!=0 && i!=numRows-1){
                    int k = j+d-i*2;
                    if(k < s.size()){
                        y.push_back(s[k]);
                    }
                }
            }
        }
        return y;
    }
};

// numRows = 5
// 0     8         16
// 1   7 9      15 17
// 2  6  10   14
// 3 5   11 13
// 4     12

// 0   4
// 1 3 5 7
// 2   6

// 0 2
// 1 3

// 0 1 2 3

7. Reverse Integer

Integer

  • 32位補(bǔ)碼表示有符號(hào)整數(shù)
  • 符號(hào)不變则剃,轉(zhuǎn)換結(jié)果可能會(huì)溢出

要點(diǎn)

  1. 十進(jìn)制:用取模和整數(shù)除法,可以得到最低位和余下的高位如捅。
  2. 整型溢出:運(yùn)算后超出表示范圍棍现,可以在運(yùn)算前,或者運(yùn)算后檢查
class Solution {
public:
    int reverse(int x) {
        int a = x>0 ? INT_MAX : INT_MIN;
        int b = a/10, c = a%10;
        int y = 0;
        for(;x>=10 || x<=-10; x /= 10)
            y = y*10 + x%10;
        if(x>0)
            return y<b || (y==b && x<=c) ? y*10+x : 0;
        else
            return y>b || (y==b && x>=c) ? y*10+x : 0;
    }
};
class Solution {
public:
    int reverse(int x) {
        int a = x>=0 ? INT_MAX : INT_MIN;
        int b = a/10, c = a%10;
        int y = 0;
        if(x>=0){
            for(;x>=10; x /= 10)
                y = y*10 + x%10;
            return y<b || (y==b && x<=c) ? y*10+x : 0;
        }else{
            for(;x<=-10; x /= 10)
                y = y*10 + x%10;
            return y>b || (y==b && x>=c) ? y*10+x : 0;
        }
    }
};

這道題 LeetCode 的 Blog 上的解法挺不錯(cuò)的

8. String to Integer (atoi)

  • 字符串轉(zhuǎn)整數(shù),實(shí)現(xiàn) C 語言的字符串類庫函數(shù)
  • 可以用 7. Reverse Integer 用到的溢出的判斷方法
    • 區(qū)分處理正負(fù)補(bǔ)碼的表示范圍
int myAtoi(char* str) {
    while(isspace(*str))
        str++;
    int neg = 0;
    switch(*str){
        case '-':
            neg = 1;
        case '+':
            str++;
            break;
    }
    if(!isdigit(*str))
        return 0;
    int a, b;
    if(!neg)
        a = INT_MAX/10, b = INT_MAX%10;
    else
        a = -(INT_MIN/10), b = -(INT_MIN%10);
    int value = 0;
    while(isdigit(*str)){
        int digit = *str-'0';
        if(value>a || (value==a && digit>b))
            return neg ? INT_MIN : INT_MAX;
        value = value*10 + digit;
        str++;
    }
    return neg ? -value : value;
}

9. Palindrome Number

  • 逐對(duì)比較
  • 十進(jìn)制自然數(shù)運(yùn)算
    取最高位和最低位
class Solution {
public:
    bool isPalindrome(int x) {
        if(x<0)
            return false;
        int c = 1;
        while(x/c>=10)
            c *= 10;
        while(x){
            if((x/c)!=(x%10))
                return false;
            x = (x%c)/10;
            c /= 100;
        }
        return true;
    }
};

10. Regular Expression Matching

  • 遞歸/回溯處理字符串后綴
  • 注意各種情況的組合
class Solution {
    bool _isMatch(const char* s, const char* p) {
        if(*p==0){
            return *s==0;
        }else if(*(p+1)=='*'){
            if(*s==0)
                return _isMatch(s, p+2);
            else if(*s==*p || *p=='.')
                return _isMatch(s+1, p) || _isMatch(s, p+2);
            else
                return _isMatch(s, p+2);
        }else{
            if(*s==0)
                return false;
            if(*s==*p || *p=='.')
                return _isMatch(s+1, p+1);
            else
                return false;
        }
    }    
public:
    bool isMatch(string s, string p) {
        return _isMatch(s.c_str(), p.c_str());
    }
};

11. Container With Most Water

  • 數(shù)組,動(dòng)態(tài)規(guī)劃谤绳,雙指針
  • 能裝最多的水
  • 雙指針列粪,從兩頭,次高往最高收縮
class Solution {
public:
    int maxArea(vector<int>& height) {
        int i = 0, j = height.size()-1;
        int m = 0;
        while(i<j){
            m = max(m, min(height[i],height[j])*(j-i));
            if(height[i] < height[j])
                i++;
            else
                j--;
        }
        return m;
    }
};

12. Integer to Roman

  • 羅馬數(shù)字轉(zhuǎn)換紊婉,輸入為 1 到 3999
class Solution {
public:
    string intToRoman(int num) {
        int integers[13] = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
        char* romans[13] = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};
        string sb;
        for(int i=0; i<13; i++){
            for(int j=num/integers[i]; j--;)
                sb += romans[i];
            num %= integers[i];
        }
        return sb;
    }
};

13. Roman to Integer

  • 羅馬數(shù)字轉(zhuǎn)換
int romanToInt(char* s) {
    int integers[13] = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
    char* romans[13] = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};
    int result = 0;
    for(int i=0; i<13; i++){
        while(!memcmp(s, romans[i], strlen(romans[i]))){
            result += integers[i];
            s += strlen(romans[i]);            
        }
    }
    return result;
}

14. Longest Common Prefix

  • 字符串比較,公共前綴
    直接按題意實(shí)現(xiàn)即可
char* longestCommonPrefix(char** strs, int strsSize) {
    char *result;
    if(strsSize==0){
        result = (char*)malloc(sizeof(char));
        result[0] = 0;
        return result;
    }
    int count = 0;
    for(;;){
        char ch = strs[0][count];
        if(ch==0)
            break;
        for(int j=1; j<strsSize; j++)
            if(strs[j][count]!=ch)
                goto end_for;
        count++;
    }
    end_for:
    result = (char*)malloc(sizeof(char)*(count+1));
    memcpy(result,strs[0],sizeof(char)*count);
    result[count] = 0;
    return result;
}

15. 3Sum

  • 排序然后查找
    • 這題有重復(fù)元素,比如 [-1, -1, 2] 戈稿,如果最后再去重可能會(huì)超時(shí)
  • 注意 .size() 返回的是 unsigned,若判斷 <.size()-1 會(huì)一直循環(huán)
    或者用哈希表
class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> result;
        sort(nums.begin(), nums.end());
        int n = nums.size();
        for(int i=0; i<n-2; i++){
            if(i!=0 && nums[i]==nums[i-1])
                continue;
            int j = i+1, k = nums.size()-1;
            while(j < k){
                int s = nums[i] + nums[j] + nums[k];
                if(s==0){
                    result.push_back({nums[i], nums[j], nums[k]});
                    j++, k--;
                }else if(s<0){
                    j++;
                }else{
                    k--;
                }
                while(j!=i+1 && nums[j]==nums[j-1])
                    j++;
                while(k!=nums.size()-1 && nums[k]==nums[k+1])
                    k--;                    
            }
        }
        return result;
    }
};
class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> result;
        sort(nums.begin(), nums.end());
        int n = nums.size();
        for(int i=0; i<n-2 && nums[i]<=0; i++){
            if(i!=0 && nums[i]==nums[i-1])
                continue;
            int j = i+1, k = nums.size()-1;
            while(j < k){
                int s = nums[i] + nums[j] + nums[k];
                if(s==0){
                    result.push_back({nums[i], nums[j], nums[k]});
                    j++, k--;
                }else if(s<0){
                    j++;
                }else{
                    k--;
                }
                while(j!=i+1 && nums[j]==nums[j-1])
                    j++;
                while(k!=nums.size()-1 && nums[k]==nums[k+1])
                    k--;                    
            }
        }
        return result;
    }
};

16. 3Sum Closest

Search

  • 先排序
  • 或者用哈希
class Solution {
public:
    int threeSumClosest(vector<int>& nums, int target) {
        int ans = 0, d = INT_MAX;
        sort(nums.begin(), nums.end());
        if(nums.size()<3)
            return 0;
        for(int i=0; i<nums.size()-2; i++){
            if(i!=0 && nums[i]==nums[i-1])
                continue;
            int j = i+1, k = nums.size()-1;
            while(j < k){
                int s = nums[i] + nums[j] + nums[k] - target;
                if(abs(s)<d){
                    d = abs(s);
                    ans = s + target;
                }
                if(s==0){
                    j++, k--;
                }else if(s<0){
                    j++;
                }else{
                    k--;
                }
                while(j!=i+1 && nums[j]==nums[j-1])
                    j++;
                while(k!=nums.size()-1 && nums[k]==nums[k+1])
                    k--;
            }
        }
        return ans;        
    }
};

17. Letter Combinations of a Phone Number

  • 遞歸讶舰,回溯鞍盗,排列組合

要點(diǎn)
回溯:

class Solution {
public:
    vector<string> letterCombinations(string digits) {
        vector<string> result;
        if(digits.size()==0)
            return result;
        string y = digits;
        int n = digits.size();
        char b[digits.size()+1];
        b[n] = 0;
        char* s[10] = {
          "","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"  
        };
        function<void(int)> f = [&](int i){
            if(i==digits.size()){
                result.push_back(b);
            }else{
                for(char *p = s[digits[i]-'0']; *p; p++){
                    b[i] = *p;
                    f(i+1);
                }
            }
        };
        f(0);
        return result;
    }
};

18. 4Sum

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        vector<vector<int>> ans;
        sort(nums.begin(), nums.end());
        for(int x:nums)printf("%d ",x);puts("");
        int n = nums.size();
        for(int i=0; i<n-3; i++){
            if(i!=0 && nums[i]==nums[i-1])
                continue;
            for(int j=i+1; j<n-2; j++){
                if(j!=i+1 && nums[j]==nums[j-1])
                    continue;
                int k = j + 1, l = n-1;
                while(k<l){
                    int sum = nums[i]+nums[j]+nums[k]+nums[l];
                    if(sum==target){
                        ans.push_back({nums[i],nums[j],nums[k],nums[l]});
                        k++, l--;
                    }else if(sum<target){
                        k++;
                    }else{
                        l--;
                    }
                    while(k!=j+1 && k<l && nums[k]==nums[k-1])
                        k++;
                    while(l!=n-1 && k<l && nums[l]==nums[l+1])
                        l--;
                }
            }
        }
        return ans;
    }
};

19. Remove Nth Node From End of List

  • 鏈表,雙指針
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
    struct ListNode* p = head;
    while(n--)
        p = p->next;
    if(p==NULL)
        return head->next;
    p = p->next;
    struct ListNode* q = head;
    while(p){
        q = q->next;
        p = p->next;
    }
    q->next = q->next->next;
    return head;
}

20. Valid Parentheses

  • 棧跳昼,先進(jìn)后出
    要點(diǎn)
    stack
bool isValid(char* s) {
    const char *ps = "([{)]}";
    int stack_size = 3;
    char *stack = (char*)malloc(sizeof(char)*stack_size);
    char *push = stack;
    for(char x; x=*s++;){
        char* found = strchr(ps, x);
        if(found){
            int a = found - ps;
            if(a<3){
                if(push==stack+stack_size){
                    stack = (char*)realloc(stack,sizeof(char)*(stack_size<<1));
                    push = stack + stack_size;
                    stack_size <<= 1;
                }
                *push++ = ps[a+3];
            }else{
                if(push<=stack || push[-1]!=x)
                    return false;
                push--;
            }
        }
    }
    return push==stack;
}

21. Merge Two Sorted Lists

  • 鏈表的節(jié)點(diǎn)操作
  • 有序序列的歸并
    要點(diǎn):節(jié)點(diǎn)題通常會(huì)要求不改變?cè)匕慵祝膊灰欢ā?/li>
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode* head = NULL;
        ListNode** append = &head; 
        for(;;){
            if(!l1){
                *append = l2;
                break;
            }
            if(!l2){
                *append = l1;
                break;
            }
            if(l1->val<l2->val){
                *append = l1;
                l1 = l1->next;
            }else{
                *append = l2;
                l2 = l2->next;
            }
            append = &(*append)->next;
        }
        return head;
    }
};

22. Generate Parentheses

  • 遞歸,回溯
class Solution {
public:
    vector<string> generateParenthesis(int n) {
        vector<string> result;
        string item(n*2, ' ');
        function<void(int,int)> f = [&](int i,int s){
            if(i==n*2){
                result.push_back(item);
                return;
            }
            if(s > 0){
                item[i] = ')';
                f(i+1, s-1);
            }
            if(s < 2*n - i){
                item[i] = '(';
                f(i+1, s+1);
            }
        };
        f(0, 0);
        return result;
    }
};

23. Merge k Sorted Lists

  • 歸并排序鹅颊,鏈表
  • 兩兩歸并敷存,次數(shù)
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2) {
    struct ListNode* head = NULL;
    struct ListNode** append = &head; 
    for(;;){
        if(!l1){
            *append = l2;
            break;
        }
        if(!l2){
            *append = l1;
            break;
        }
        if(l1->val<l2->val){
            *append = l1;
            l1 = l1->next;
        }else{
            *append = l2;
            l2 = l2->next;
        }
        append = &(*append)->next;
    }
    return head;
} 
struct ListNode* mergeKLists(struct ListNode** lists, int listsSize) {
    if(listsSize==0)
        return NULL;
    if(listsSize==1)
        return lists[0];
    if(listsSize==2)
        return mergeTwoLists(lists[0], lists[1]);
    return mergeTwoLists(mergeKLists(lists,listsSize/2),mergeKLists(lists+listsSize/2,listsSize-listsSize/2));
}

24. Swap Nodes in Pairs

  • 鏈表
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        auto list = new ListNode(-1);
        list->next = head;
        auto p = list;
        while(p->next){
            auto a = p->next;
            auto b = a->next;
            if(!b)
                break;
            auto c = b->next;
            a->next = c;
            b->next = a;
            p->next = b;
            p = a;
        }
        return list->next;
    }
};

25. Reverse Nodes in k-Group

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseKGroup(ListNode* head, int k) {
        auto list = new ListNode(-1);
        list->next = head;
        auto last = list;
        for(;;){
            auto list2 = last;
            int n = k;
            while(n && last->next){
                n--;
                last = last->next;
            }
            if(n)
                break;
            ListNode* prev = last->next;
            ListNode* node = list2->next;
            for(int i=0; i<k; i++){
                auto next = node->next;
                node->next = prev;
                prev = node;
                node = next;
            }
            last = list2->next;
            list2->next = prev;
            
        }
        return list->next;
    }
};
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* reverseKGroup(struct ListNode* head, int k) {
    struct ListNode **append = &head;
    for(;;){
        struct ListNode **list = append;
        int n = k;
        while(n && *append){
            append = &(*append)->next;
            n--;
        }
        if(n)
            break;
        struct ListNode *prev = *append;
        struct ListNode *node = *list;
        for(int i=0; i<k; i++){
            struct ListNode *next = node->next;
            node->next = prev;
            prev = node;
            node = next;
        }
        auto append2 = &(*list)->next;        
        *list = prev;
        append = append2;
    }
    return head;
}

26. Remove Duplicates from Sorted Array

  • 去重,通過排序。
int removeDuplicates(int* nums, int numsSize) {
    if(numsSize==0)
        return 0;
    int *s = nums;
    for(int i=1; i<numsSize;i++){
        if(nums[i]!=*s){
            *++s = nums[i];
        }
    }
    return s - nums + 1;
}

27. Remove Element

  • 數(shù)組
  • 雙指針
int removeElement(int* nums, int numsSize, int val) {
    int *s = nums;
    for(int i=0; i<numsSize; i++){
        if(nums[i]!=val)
            *s++ = nums[i];
    }
    return s - nums;
}

28. Implement strStr()

Search

  • 庫函數(shù) strstr 實(shí)現(xiàn)為 O(MN) 锚烦,平時(shí)需要 O(N) 就用正則表達(dá)式生成狀態(tài)機(jī)

要點(diǎn)

  1. 前綴:字符串頭部的連續(xù)字符構(gòu)成的子串觅闽。該子串可能會(huì)在字符串內(nèi)重復(fù)出現(xiàn)。
class Solution {
    int* built_table(string& m){
        int *T = new int[m.size()];
        T[0] = -1;
        T[1] = 0;
        for(int i=2, j=0; i<m.size(); ){
            printf("> %d \n",i);
            if(m[i-1] == m[j]){
                T[i] = j + 1;
                i++, j++;
            }else if(j>0){
                j = T[j];
            }else{
                T[i] = 0;
                i++;
            }
        }
        return T;
    }
    int search(string &s, string &m){
        if(m.size()==0)
            return 0;
        auto next = built_table(m);
        for(int i=0, j=0; i<s.size();){
            if(m[j]==s[i]){
                if(j+1==m.size()){
                    return i-j;
                }else{
                    i++, j++;
                }
            }else{
                if(next[j]!=-1){
                    j = next[j];
                }else{
                    i++;
                    j = 0;
                }
            }
        }
        return -1;
    }
public:
    int strStr(string haystack, string needle) {
        return search(haystack, needle);
    }
};

稍微改一下涮俄,上面的刪掉蛉拙,也有其他寫法

class Solution {
    int* built_table(string& m){
        int *T = new int[m.size()];
        T[0] = -1;
        T[1] = 0;
        for(int i=2, j=0; i<m.size(); ){
            if(m[i-1] == m[j]){
                T[i] = j + 1;
                i++, j++;
            }else if(j!=0){
                j = T[j];
            }else{
                T[i] = 0;
                i++;
            }
        }
        return T;
    }
    int search(string &s, string &m){
        if(m.size()==0)
            return 0;
        auto next = built_table(m);
        for(int i=0, j=0; i<s.size();){
            if(m[j]==s[i]){
                if(j+1==m.size())
                    return i-j;
                else
                    i++, j++;
            }else{
                if(j!=0)
                    j = next[j];
                else
                    i++;
            }
        }
        return -1;
    }
public:
    int strStr(string haystack, string needle) {
        return search(haystack, needle);
    }
};

這樣也行

int strStr(char* s1, char* s2) {
    int m = strlen(s2);
    if(m==0)
        return 0;
    int n = strlen(s1);
    int b[m+1];
    int i, j;
    i = 0, j = -1;
    b[i] = j;
    while(i<m){
        while(j>=0 && s2[i]!=s2[j])
            j = b[j];
        i++, j++;
        if(s2[i]==s2[j])
            b[i] = b[j];
        else
            b[i] = j;
    }
    i = j = 0;
    while(i<n){
        while(j>=0 && s1[i]!=s2[j])
            j = b[j];
        i++, j++;
        if(j==m)
            return i-j;
    }
    return -1;
}
int strStr(char* s1, char* s2) {
    int m = strlen(s2);
    if(m==0)
        return 0;
    int n = strlen(s1);
    int b[m+1];
    int i, j;
    i = 0, j = -1;
    b[i] = j;
    while(i<m){
        while(j>=0 && s2[i]!=s2[j])
            j = b[j];
        i++, j++;
        b[i] = j;
    }
    i = j = 0;
    while(i<n){
        while(j>=0 && s1[i]!=s2[j])
            j = b[j];
        i++, j++;
        if(j==m)
            return i-j;
    }
    return -1;
}

29. Divide Two Integers

  • 整數(shù)運(yùn)算,通過除法和取模
int divide(int dividend, int divisor) {
    if(divisor==0)
        return INT_MAX;
    unsigned a = dividend>=0 ? dividend : -dividend;
    unsigned b = divisor>=0 ? divisor : -divisor;
    unsigned c = 0;
    int n = 0;
    for(unsigned i=b; i<a; i<<=1)
        n++;
    for(int i=n; i>=0; i--){
        if((b<<i)<=a){ 
            c += (1<<i);
            a -= (b<<i);
        }
    }
    if((dividend>0 && divisor<0) || (dividend<0 && divisor>0))
        return -c;
    return c>INT_MAX ? INT_MAX : c;
}

30. Substring with Concatenation of All Words

Array

class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        vector<int> ans;
        unordered_map<string,int> count;
        for(auto& x: words)
            count[x]++;
        int n = words.at(0).size();
        int m = n*words.size();
        for(int i=0,e = s.size()-m+1; i<e; i++){
            unordered_map<string,int> copy(count);
            for(int j=0; j<words.size(); j++){
                auto x = s.substr(i+j*n, n);
                auto it = copy.find(x);
                if(it!=copy.end() && it->second)
                    copy[x]--;
                else
                    goto out;
            }
            ans.push_back(i);
            out:;
        }
        return ans;
    }
};

31. Next Permutation

  • 排列組合彻亲,求下一個(gè)排列
  • 函數(shù)不保存額外的狀態(tài)孕锄,每次調(diào)用獨(dú)立
  • 三個(gè)元素則依次為 123,132,213,231,312,321
    • 值的大小按升序排列,123 開始 321 結(jié)束
    • 每一位的值表示序號(hào)苞尝,唯一且有限個(gè)
  • 從右往左找到第一個(gè)小于右側(cè)元素的 A
    • 這是可以增大的最低位(從右往左)
      • A 右側(cè)一定是降序序列
    • 沒找到(如 321)則逆置整個(gè)排列
    • 找到則找到比 A 大的最低位 B
      • B 一定是 A 右側(cè)比 A 大的最小值
    • A, B 互換畸肆,低于 A 的位逆置(從降序變成升序)

要點(diǎn)

  1. 升序:等長(zhǎng)序列之間也可構(gòu)成偏序關(guān)系。
class Solution {
public:
    void nextPermutation(vector<int>& nums) {
        int n = nums.size();
        int l = n-1;
        while(l>0 && !(nums[l-1]<nums[l]))
            l--;
        if(l>0){
            int r = n-1;
            while(!(nums[l-1]<nums[r]))
                r--;
            swap(nums[l-1], nums[r]);
        }
        for(int r=n-1;l<r;l++,r--)
            swap(nums[l], nums[r]);
            
    }
};

32. Longest Valid Parentheses

  • 可以用動(dòng)態(tài)規(guī)劃來做
class Solution {
public:
    int longestValidParentheses(string s) {
        int len = 0, start = -1;
        stack<int> st;
        for(int i=0; i<s.size(); i++){
            if(s[i]=='('){
                st.push(i);
            }else if(!st.empty()){
                st.pop();
                if(!st.empty()){
                    len = max(len, i-st.top());
                }else{
                    len = max(len, i-start);
                }
            }else{
                start = i;
            }
        }
        return len;
    }
};

33. Search in Rotated Sorted Array

Search

  • 二分查找
int search(int* A, int n, int target) {
    int a = 0, b = n;
    while(a<b){
        int c = a+(b-a)/2;
        if(A[c]==target){
            return c;
        }else if(A[a]<=A[c]){
            if(A[a]<=target && target<A[c])
                b = c;
            else
                a = c + 1;
        }else{
            if(A[c]<target && target<=A[b-1])
                a = c + 1;
            else
                b = c;
        }
    }
    return -1;
}

34. Search for a Range

Search

  • 二分查找
class Solution {
    int lower(vector<int>& nums, int target){
        int a = 0, b = nums.size();
        while(a<b){
            int c = (a+b)/2;
            if(nums[c]<target){
                a = c + 1;
            }else{
                b = c;
            }
        }
        return b;   
    }
    int upper(vector<int>& nums, int target){
        int a = 0, b = nums.size();
        while(a<b){
            int c = (a+b)/2;
            if(nums[c]<=target){
                a = c + 1;
            }else{
                b = c;
            }
        }
        return a-1;
    }
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        int low = lower(nums,target);
        int high = upper(nums,target);
        if(low<=high)
            return {lower(nums,target), upper(nums,target)};
        else
            return {-1, -1};
    }
};

35. Search Insert Position

  • 注意右邊界是否包含
    • 以及終止條件野来,和連續(xù)相等元素的處理
int searchInsert(int* nums, int numsSize, int target) {
    int a = 0, b = numsSize;
    while(a<b){
        int c = (a+b)/2;
        if(nums[c]==target){
            return c;
        }else if(nums[c]<target){
            a = c + 1;
        }else{
            b = c;
        }
    }
    return a;
}

36. Valid Sudoku

  • 判斷數(shù)獨(dú)局面是否正確
    三個(gè)條件
class Solution {
public:
    bool isValidSudoku(vector<vector<char>>& board) {
        bool flag[9];
        memset(flag, 0, sizeof(bool)*9);
        for(int i=0; i<9; i++){
            for(int j=0; j<9; j++){
                if(board[i][j]=='.')
                    continue;
                if(flag[board[i][j]-'1'])
                    return false;
                flag[board[i][j]-'1'] = true;
            }
            memset(flag, 0, sizeof(bool)*9);
            for(int j=0; j<9; j++){
                if(board[j][i]=='.')
                    continue;
                if(flag[board[j][i]-'1'])
                    return false;
                flag[board[j][i]-'1'] = true;
            }
            memset(flag, 0, sizeof(bool)*9);
            for(int j=0; j<9; j++){
                int x=(i%3)*3+j%3;
                int y=(i/3)*3+j/3;
                if(board[x][y]=='.')
                    continue;
                if(flag[board[x][y]-'1'])
                    return false;
                flag[board[x][y]-'1'] = true;                
            }
            memset(flag, 0, sizeof(bool)*9);
        }
        return true;
    }
};

37. Sudoku Solver

  • 回溯
  • 有其他高效的算法
class Solution {
public:
    void solveSudoku(vector<vector<char>>& board) {
        unsigned t[3][9] = {0};
        for(int y=0; y<9; y++)
            for(int x=0; x<9; x++){
                int z = x/3 + y/3*3;
                if(board[y][x]!='.'){
                    int b = board[y][x]-'1';
                    t[0][x] |= (1<<b);
                    t[1][y] |= (1<<b);
                    t[2][z] |= (1<<b);
                }
                 
            }
        function<bool(int)> f = [&](int k){
            if(k==81){
                return true;
            }
            int x = k%9, y = k/9;
            if(board[y][x]!='.')
                return f(k+1);
            int z = x/3 + y/3*3;
            
            for(int i=0; i<9; i++){
                if (t[0][x]&(1<<i)||t[1][y]&(1<<i)||t[2][z]&(1<<i))
                    continue;
                t[0][x] |= (1 << i);
                t[1][y] |= (1 << i);
                t[2][z] |= (1 << i);
                board[y][x] = i + '1';
                if(f(k + 1))
                    return true;;
                board[y][x] = '.';
                t[0][x] &= ~(1 << i);
                t[1][y] &= ~(1 << i);
                t[2][z] &= ~(1 << i);                
            }
            return false;
        };
        f(0);
    }
};

38. Count and Say

  • 字符串
class Solution {
public:
    string countAndSay(int n) {
        string s("1");
        while(--n){
            string s2;
            for(auto it=s.begin(); it!=s.end();){
                char ch = *it;
                auto it2 = find_if(it, s.end(), [ch](char x){return x!=ch;});
                int count = distance(it, it2);
                s2 += '0'+count;
                s2 += ch;
                it = it2;
            }
            swap(s, s2);
        }
        return s;
    }
};

39. Combination Sum

  • 排列組合類型的問題恼除,遞歸/回溯法
  • 該類某項(xiàng)可出現(xiàn)任意多次
  • 組合問題各組合升序排列
class Solution {
public:
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        vector<vector<int>> result;
        int n = candidates.size();
        int sum = 0;
        vector<int> item;
        function<void(int)> loop = [&](int i){
            if(sum>target)
                return;
            if(sum==target){
                result.push_back(item);
                return;
            }
            for(int j=i;j<n;j++){
                int x = candidates[j];
                sum += x;
                item.push_back(x);
                loop(j);
                sum -= x;
                item.pop_back();
            }
        };
        loop(0);
        return result;
    }
};

40. Combination Sum II

  • 排列組合類的問題
  • 相比 39. Combination Sum 這題有重復(fù)元素
    • 重復(fù)運(yùn)算可以用哈希表或者排序來處理
class Solution {
public:
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        vector<vector<int>> result;
        sort(begin(candidates), end(candidates));
        const int n = candidates.size();
        vector<int> item;
        function<void(int,int)> loop = [&](int i, int sum){
            if(sum==target){
                result.push_back(item);
                return;
            }
            int y = -1;
            for(int j=i; j<n; j++){
                int x = candidates[j];
                if(x==y)
                    continue;
                if(sum+x>target)
                    break;
                item.push_back(x);
                loop(j+1, sum+x);
                item.pop_back();
                y = x;
            }
        };
        loop(0, 0);
        return result;
    }
};
class Solution {
public:
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        vector<vector<int>> result;
        sort(begin(candidates), end(candidates));
        const int n = candidates.size();
        vector<int> item;
        function<void(int,int)> loop = [&](int i, int sum){
            if(sum==target){
                result.push_back(item);
                return;
            }
            for(int j=i; j<n; j++){
                int x = candidates[j];
                if(j!=i && x==candidates[j-1])
                    continue;
                if(sum+x>target)
                    break;
                item.push_back(x);
                loop(j+1, sum+x);
                item.pop_back();
            }
        };
        loop(0, 0);
        return result;
    }
};

41. First Missing Positive

  • 題目限制挺具體的
  • 數(shù)組排列為 [1,2,3,...]
    • 滿足 A[i]=i+1
    • 不滿足則 iA[i]-1 交換
class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        int n = nums.size();
        for(int i=0; i<n; i++)
            while(nums[i]>0 && nums[i]<=n && nums[i]!=nums[nums[i]-1])
                swap(nums[i],nums[nums[i]-1]);
        for(int i=0; i<n; i++)
            if(nums[i]!=i+1)
                return i+1;
        return n+1;
    }
};

42. Trapping Rain Water

Array

  • 數(shù)組,雙指針(下標(biāo))
class Solution {
public:
    int trap(vector<int>& height) {
        int i = 0, j = height.size()-1;
        int a = 0;
        int h = 0;
        while(i<j){
            if(height[i]<height[j]){
                h = max(h, height[i]);
                a += h - height[i];
                i++;
            }else{
                h = max(h, height[j]);
                a += h - height[j];
                j--;
            }
        }
        return a;
    }
};

43. Multiply Strings

整數(shù)

  • 大數(shù)
  • 可以 4 個(gè)十進(jìn)制位一個(gè) 32 位整型
char* multiply(char* num1, char* num2) {
    int n1 = strlen(num1);
    int n2 = strlen(num2);
    int n3 = n1 + n2;
    char *num3 = (char*)calloc(n3+1, sizeof(char));
    for(int i=0; i<n1; i++){
        int a = num1[n1-i-1]-'0';
        int c = 0;
        for(int j=0; j<n2; j++){
            int b = num2[n2-j-1]-'0';
            int k = n3 - i - j - 1;
            c += a*b + num3[k];
            num3[k] = c%10;
            c /= 10;
        }
        num3[n3-n2-i-1] += c;
    }
    char *p = num3;
    for(int i=0; i<n3-1; i++){
        if(*p!=0)
            break;
        p++;
    }
    for(char *q=p; q<num3+n3; q++)
        *q += '0';
    return p;
}

44. Wildcard Matching

  • 字符串搜索
  • 通配符
  • 遇到星號(hào)時(shí)曼氛,記錄下位置
class Solution {
    bool isMatch(const char* s, const char* p){
        bool star = false;
        const char *ss=s, *pp=p;
        for(;;){    
            if(*s==0){
                while(*p=='*')
                    p++;
                return *p==0;
            }else if(*p=='?'){
                if(*s==0)
                    return false;
                s++, p++;       
            }else if(*p=='*'){
                while(*++p=='*')
                    ;
                star = true;
                ss=s, pp=p;
            }else if(*p==*s){
                s++, p++;
            }else if(star){
                ss++;
                s=ss, p=pp;
            }else{
                return false;
            }
        }
    }
public:
    bool isMatch(string s, string p) {
        return isMatch(s.c_str(), p.c_str());
    }
};

45. Jump Game II

class Solution {
public:
    int jump(vector<int>& nums) {
        int step = 0;
        int dist = 0;
        int arri = 0;
        for(int i=0; i<nums.size(); i++){
            if(i>arri){
                arri = dist;
                step += 1;
            }
            dist = max(dist , nums[i]+i);
        }
        return step;
    }
};

46. Permutations

  • 排列組合問題豁辉,求全排列
  • 遞歸/回溯
class Solution {
public:
    vector<vector<int>> permute(vector<int>& nums) {
        vector<vector<int>> result;
        function<void(int)> loop = [&](int i){
            if(i==nums.size()){
                result.push_back(nums);
                return;
            }
            for(int j=i; j<nums.size(); j++){
                swap(nums[i],nums[j]);
                loop(i+1);
                swap(nums[i],nums[j]);
            }
        };
        loop(0);
        return result;
    }
};

47. Permutations II

  • 排列組合,全排列舀患,有重復(fù)元素
class Solution {
public:
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        vector<vector<int>> result;
        if(nums.empty())
            return result;
        unordered_map<int,int> h;
        for(int x: nums)
            h[x]++;
        vector<int> item;
        function<void(int)> loop = [&](int i){
            if(i==nums.size()){
                result.push_back(item);
                return;
            }
            for(auto p: h){
                if(p.second){
                    item.push_back(p.first);
                    h[p.first]--;
                    loop(i+1);
                    h[p.first]++;
                    item.pop_back();
                }
            }
        };
        loop(0);
        return result;
    }
};

48. Rotate Image

  • 二維數(shù)組中元素交換
  • 區(qū)分尺寸奇偶
  • 也可以做兩次鏡像徽级。
class Solution {
public:
    void rotate(vector<vector<int>>& matrix) {
        int n = matrix.size();
        int s = n - 1;
        int e = n&1 ? n/2+1 : n/2;
        for(int i=0; i<e; i++)
            for(int j=0; j<n/2; j++){
                int t = matrix[i][j];
                matrix[i][j] = matrix[s-j][i];
                matrix[s-j][i] = matrix[s-i][s-j];
                matrix[s-i][s-j] = matrix[j][s-i];
                matrix[j][s-i] = t;
            }
    }
};

49. Group Anagrams

  • 實(shí)現(xiàn) group 函數(shù)
    可以利用哈希表或者排序,需要自行實(shí)現(xiàn)轉(zhuǎn)化為key
class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        unordered_map<string,vector<string>> h;
        for(auto& s:strs){
            auto k = s;
            sort(begin(k),end(k));
            h[k].push_back(s);
        }
        vector<vector<string>> xs;
        for(auto it = h.begin(); it!=h.end(); ++it){
            vector<string> x;
            for(auto& e: it->second)
                x.push_back(e);
            xs.push_back(x);
        }
        return xs;
    }
};

50. Pow(x, n)

  • 遞歸
  • 無符號(hào)數(shù)的位移
    • C 用操作數(shù)的類型
    • Java 里用操作符區(qū)分
  • 分奇偶
  • 有點(diǎn)小問題聊浅。

要點(diǎn)
位移:無符號(hào)位移高位補(bǔ)0餐抢,有符號(hào)位移補(bǔ)最高位。正數(shù)對(duì)應(yīng)除以2低匙。

double myPow(double x, int n)
{
    int neg = n<0;
    unsigned exp = neg ? -(unsigned)n : n;
    double y = 1;
    while(exp)
    {
        if(exp&1)
            y *= x;
        x *= x;
        exp >>= 1;
    }
    return neg ? 1/y : y;
}
class Solution {
public:
    double myPow(double x, int n) {
        printf("n: %d\n",n);
        if(n==0)
            return 1;
        if(n==-1)
            return 1/x;
        double f = myPow(x,n>>1);
        return n%2 ? f*f*x : f*f;
    }
};

注意 C 的整數(shù)除法是向下取整的

51. N-Queens

  • 八皇后
  • 求全部解
  • 回溯
class Solution {
    vector<vector<string>> ans;
    int n;
    vector<bool> f1, f2, f3;
    vector<int> path;
    void f(int i){
        if(i==n){
            vector<string> item(n);
            for(int i=0; i<n ;i++){
                string line(n, '.');
                line[path[i]] = 'Q';
                swap(item[i], line);
            }
            ans.push_back(item);
            return;
        }
        for(int j=0; j<n; j++){
            if(f1[j] || f2[i+j] || f3[n-i+j])
                continue;
            path[i] = j;
            f1[j] = f2[i+j] = f3[n-i+j] = true;
            f(i+1);
            f1[j] = f2[i+j] = f3[n-i+j] = false;
        }
    }    
public:
    vector<vector<string>> solveNQueens(int n) {
        this->n = n;
        f1.resize(n, false);
        f2.resize(2*n+1, false);
        f3.resize(2*n+1, false);
        path.resize(n, false);
        f(0);
        return ans;
    }
};

52. N-Queens II

  • 八皇后
    同上一題旷痕,返回解的個(gè)數(shù)
class Solution {
    int count;
    int n;
    vector<bool> f1, f2, f3;
    void f(int i){
        if(i==n){
            count++;
            return;
        }
        for(int j=0; j<n; j++){
            if(f1[j] || f2[i+j] || f3[n-i+j])
                continue;
            f1[j] = f2[i+j] = f3[n-i+j] = true;
            f(i+1);
            f1[j] = f2[i+j] = f3[n-i+j] = false;
        }
    }
public:
    int totalNQueens(int n) {
        count = 0;
        this->n = n;
        f1.resize(n, false);
        f2.resize(2*n+1, false);
        f3.resize(2*n+1, false);
        f(0);
        return count;
    }
};

53. Maximum Subarray

  • 數(shù)組,動(dòng)態(tài)規(guī)劃
  • 挺有趣的一道題顽冶!
class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int m = INT_MIN;
        int d = 0;
        for(int x: nums){
            d = max(d+x, x);
            m = max(m, d);
        }
        return m;
    }
};

54. Spiral Matrix

  • 按照題意實(shí)現(xiàn)欺抗,小心不要越界
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* spiralOrder(int** matrix, int matrixRowSize, int matrixColSize) {
    int *result = (int*)malloc(sizeof(int)*(matrixRowSize*matrixColSize));
    int *s = result;
    int left = 0, right = matrixColSize-1;
    int top = 0, bottom = matrixRowSize-1;
    for(;left<=right && top<=bottom;){
        for(int i=left; i<=right; i++)
            *s++ = matrix[top][i];
        for(int i=top+1; i<=bottom; i++)
            *s++ = matrix[i][right];
        if(top==bottom || left==right)
            break;
        for(int i=right-1; i>=left; i--)
            *s++ = matrix[bottom][i];
        for(int i=bottom-1; i>=top+1; i--)
            *s++ = matrix[i][left];
        left++, right--, top++, bottom--;
    }
    return result;
}

55. Jump Game

  • 題目要求判斷是否能抵達(dá)終點(diǎn)
class Solution {
public:
    bool canJump(vector<int>& nums) {
        int dist = 0;
        for(int i=0; i<=dist; i++){
            dist = max(dist, nums[i]+i);
            if(dist>=nums.size()-1)
                return true;
        }
        return false;
    }
};

56. Merge Intervals

/**
 * Definition for an interval.
 * struct Interval {
 *     int start;
 *     int end;
 *     Interval() : start(0), end(0) {}
 *     Interval(int s, int e) : start(s), end(e) {}
 * };
 */
class Solution {
public:
    vector<Interval> merge(vector<Interval>& intervals) {
        vector<Interval> result;
        sort(begin(intervals),end(intervals),
            [](Interval& a,Interval& b){return a.start<b.start;});
        for(auto& x: intervals){
            if(result.empty())
                result.push_back(x);
            else if(x.start <= result.back().end)
                result.back().end = max(x.end, result.back().end);
            else
                result.push_back(x);
        }
        return result;
    }
};

57. Insert Interval

  • 一次移除一個(gè)元素不好。
/**
 * Definition for an interval.
 * struct Interval {
 *     int start;
 *     int end;
 *     Interval() : start(0), end(0) {}
 *     Interval(int s, int e) : start(s), end(e) {}
 * };
 */
class Solution {
public:
    vector<Interval> insert(vector<Interval>& intervals, Interval newInterval) {
        for(auto it = intervals.begin(); it!=intervals.end();){
            if(newInterval.end < it->start){
                intervals.insert(it, newInterval);
                return intervals;
            }else if(newInterval.start <= it->end){
                newInterval.start = min(newInterval.start, it->start);
                newInterval.end = max(newInterval.end, it->end);
                it = intervals.erase(it);
            }else{
                ++it;
            }
        }
        intervals.push_back(newInterval);
        return intervals;
    }
};
/**
 * Definition for an interval.
 * struct Interval {
 *     int start;
 *     int end;
 *     Interval() : start(0), end(0) {}
 *     Interval(int s, int e) : start(s), end(e) {}
 * };
 */
class Solution {
public:
    vector<Interval> insert(vector<Interval>& intervals, Interval newInterval) {
        vector<Interval> result;
        auto it=intervals.begin();
        while(it!=intervals.end()){
            if(newInterval.end < it->start){
                break;
            }else if(newInterval.start <= it->end){
                newInterval.start = min(newInterval.start, it->start);
                newInterval.end = max(newInterval.end, it->end);
            }else{
                result.push_back(*it);
            }
            ++it;
        }
        result.push_back(newInterval);
        while(it!=intervals.end()){
            result.push_back(*it);
            ++it;
        }
        return result;
    }
};

58. Length of Last Word

class Solution {
public:
    int lengthOfLastWord(string s) {
        int y = 0;
        int count = 0;
        for(auto p = s.c_str();*p;p++){
            if(count!=0)
                y = 0;
            if(*p==' '){
                if(count!=0){
                    y = count;
                    count = 0;
                }
            }else
                count++;
        }
        return count ? count : y;
    }
};

59. Spiral Matrix II

  • 拿之前那題改一下强重,讀變成寫
  • 對(duì)照 54. Spiral Matrix
/**
 * Return an array of arrays.
 * Note: The returned array must be malloced, assume caller calls free().
 */
int** generateMatrix(int n) {
    int **matrix = (int**)malloc(sizeof(int*)*n);
    for(int i=0; i<n ;i++)
        matrix[i] = (int*)malloc(sizeof(int)*n);
    int count = 1;
    int left = 0, right = n-1;
    int top = 0, bottom = n-1;
    for(;left<=right && top<=bottom;){
        for(int i=left; i<=right; i++)
            matrix[top][i] = count++;
        for(int i=top+1; i<=bottom; i++)
            matrix[i][right] = count++;
        if(top==bottom || left==right)
            break;
        for(int i=right-1; i>=left; i--)
            matrix[bottom][i] = count++;
        for(int i=bottom-1; i>=top+1; i--)
            matrix[i][left] = count++;
        left++, right--, top++, bottom--;
    }
    return matrix;
}

60. Permutation Sequence

  • 排列組合
  • n 個(gè)元素有 n! 個(gè)排列绞呈,n-1 個(gè)元素有 (n-1)! 個(gè)排列
  • 取模/整數(shù)除法運(yùn)算是對(duì)從 0 開始的整數(shù)
char* getPermutation(int n, int k) {
    char *s = (char*)malloc(sizeof(char)*(n+1));
    s[n] = 0;
    for(int i=0; i<n; i++)
        s[i] = '1' + i;
    int a = 1;
    for(int i=2; i<n; i++)
        a *= i;
    k--;
    for(int i=0; k; i++){
        int j = k/a;
        char t = s[i+j];
        for(int p=i+j; p>i; p--)
            s[p] = s[p-1];
        s[i] = t;
        k %= a;
        a /= n-1-i;
    }
    return s;
}

61. Rotate List

  • 鏈表
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* rotateRight(ListNode* head, int k) {
        if(!head || !k)
            return head;
        ListNode** p = &head;
        int n = 0;
        while(*p){
            n++;
            p = &(*p)->next;
        }
        *p = head;
        for(int c=n-k%n; c--;)
            p = &(*p)->next;
        head = *p;
        *p = NULL;
        return head;
    }
};

62. Unique Paths

  • 排列組合
  • 動(dòng)態(tài)規(guī)劃
int nchoosek(int n, int k){
    long long res = 1;
    for(int i=0;i<k;i++)
        res *= n-i;
    for(int i=1;i<=k;i++)
        res /= i;
    return res;
}
int uniquePaths(int m, int n) {
    return nchoosek(m+n-2, (m<n ? m : n)-1);
}

63. Unique Paths II

  • 動(dòng)態(tài)規(guī)劃,挺有趣的一道題
int uniquePathsWithObstacles(int** obstacleGrid, int obstacleGridRowSize, int obstacleGridColSize) {
    int *d = (int*)malloc(sizeof(int)*obstacleGridColSize);
    memset(d,0,sizeof(int)*obstacleGridColSize);
    d[0] = 1 - obstacleGrid[0][0];
    for(int y=0; y<obstacleGridRowSize; y++){
        d[0] = d[0] ? 1-obstacleGrid[y][0] : 0;
        for(int x=1; x<obstacleGridColSize; x++)
            d[x] = obstacleGrid[y][x] ? 0 : (d[x-1]+d[x]);
    }
    return d[obstacleGridColSize-1];
}

64. Minimum Path Sum

  • 動(dòng)態(tài)規(guī)劃
  • 遞推關(guān)系 D[i][j] = grid[i][j] + min(D[i-1][j], D[i][j-1])
int minPathSum(int** grid, int gridRowSize, int gridColSize) {
    int D[gridColSize];
    D[0] = grid[0][0];
    for(int i=1; i<gridColSize; i++)
        D[i] = grid[0][i] + D[i-1];
    for(int i=1; i<gridRowSize; i++){
        D[0] += grid[i][0];
        for(int j=1; j<gridColSize; j++)
            D[j] = grid[i][j] + (D[j]<=D[j-1] ? D[j] : D[j-1]);
    }
    return D[gridColSize-1];
}

65. Valid Number

  • 狀態(tài)機(jī)间景,正則表達(dá)式
bool isNumber(char* s) {
    char* e;
    double a = strtof(s, &e);
    if(e==s)
        return false;
    while(isspace(*e))
        e++;
    return *e==0;
}

66. Plus One

  • 挺有趣的題佃声,大數(shù)和排列組合的題目中會(huì)用到。
class Solution {
public:
    vector<int> plusOne(vector<int>& digits) {
        for(int i=digits.size()-1; i>=0; i--){
            if(digits[i]<9){
                digits[i]++;
                return digits;
            }
            digits[i] = 0;
        }
        digits.insert(digits.begin(), 1);
        return digits;
    }
};
class Solution {
public:
    vector<int> plusOne(vector<int>& digits) {
        vector<int> result(digits.size());
        int carry = 1;
        for(int i=digits.size()-1; i>=0; i--){
            int digit = digits[i] + carry;
            result[i] = digit%10;
            carry = digit/10;
        }
        if(carry)
            result.insert(result.begin(), carry);
        return result;
    }
};

67. Add Binary

  • 大數(shù)
class Solution {
public:
    string addBinary(string a, string b) {
        string c;
        int m = a.size(), n = b.size();
        int carry = 0;
        int i = m-1, j = n-1;
        for(int k=0, e=max(m,n); k<e; k++){
            carry += i>=0 && a[i--]=='1';
            carry += j>=0 && b[j--]=='1';
            c += '0'+(carry&1);
            carry >>= 1;
        }
        if(carry)
            c += '1';
        reverse(c.begin(), c.end());
        return c;
    }
};

68. Text Justification

  • 細(xì)節(jié)略多
class Solution {
public:
    vector<string> fullJustify(vector<string>& words, int maxWidth) {
        vector<string> ans;
        int start = 0;
        int size = 0;
        for(int i=0; i<words.size(); i++){
            string line;
            size += words[i].size();
            int c = i - start - 1;
            if(size+c>=maxWidth){
                size = words[i].size();
                int space = maxWidth;
                for(int j=start; j<i; j++)
                    space -= words[j].size();
                line += words[start++];
                if(c==0){
                    line.append(space, ' ');
                }else{
                    for(; start<i; c--){
                        int r = space/c+!!(space%c);
                        line.append(r, ' ');
                        space -= r;
                        line += words[start++];
                    }
                }
                ans.push_back(line);
            }
        }
        if(start<words.size()){
            string line;
            for(int i=start;i<words.size(); i++){
                if(!line.empty())
                    line += ' ';
                line += words[i];
            }
            line.append(maxWidth-line.size(), ' ');
            ans.push_back(line);
        }
        return ans;
    }
};

69. Sqrt(x)

  • 二分法
  • 牛頓法
int mySqrt(int x) {
    int a = 1, b = x;
    while(a<=b){
        int c = (a+b)/2;
        if(c==x/c)
            return c;
        else if(c<x/c)
            a = c+1;
        else
            b = c-1;
    }
    return b;
}

70. Climbing Stairs

  • 斐波那契數(shù)列
    • 下標(biāo)為臺(tái)階個(gè)數(shù)倘要,值為路徑個(gè)數(shù)
    • 滿足 a_n = a{n-1}+a{n-1}, a_1=1, a_2=2
int climbStairs(int n) {
    int a = 0, b = 1;
    while(n--){
        int c = a+b;
        a = b, b = c;
    }
    return b;
}

71. Simplify Path

class Solution {
public:
    string simplifyPath(string path) {
        vector<string> stack;
        auto it = path.begin();
        while(it!=path.end()){
            ++it;
            auto end = find(it,path.end(),'/');
            string s(it, end);
            if(s==".."){
                if(!stack.empty())
                    stack.pop_back();
            }else if(!s.empty() && s!="."){
                stack.push_back(s);
            }
            it = end;
        }
        if(stack.empty())
            return "/";
        string result;
        for(auto& s: stack){
            result += "/";
            result += s;
        }
        return result;
    }
};

72. Edit Distance

DP

  • 編輯距離
  • 動(dòng)態(tài)規(guī)劃圾亏,按字符
    • 相等 d[i][j] = d[i-1][j-1]
    • 替換 d[i][j] = d[i-1][j-1]+1
    • 添加 d[i][j] = d[i][j-1]+1
    • 刪除 d[i][j] = d[i-1][j]+1
  • 寫成遞歸的形式或迭代的形式

動(dòng)規(guī)

class Solution {
public:
    int minDistance(string word1, string word2) {
        vector<int> d(word2.size()+1);
        for(int i=0; i<=word2.size(); i++)
            d[i] = i;
        for(int i=1; i<=word1.size(); i++){
            int c = d[0];
            d[0] = i;
            for(int j=1; j<=word2.size() ;j++){
                int t = d[j];
                if(word1[i-1]==word2[j-1])
                    d[j] = c;
                else
                    d[j] = min(c, min(d[j-1],d[j])) + 1;
                c = t;
            }
        }
        return d[word2.size()];
    }
};

遞歸

class Solution {
public:
    int minDistance(string word1, string word2) {
        map<pair<int,int>,int> h;
        function<int(int,int)> d = [&](int i, int j)->int{
            if(h.count({i,j}))
                return h[{i,j}];
            if(i==word1.size())
                return word2.size()-j;
            if(j==word2.size())
                return word1.size()-i;
            int a = (word1[i]==word2[j] ? 0: 1)+d(i+1, j+1);
            int b = 1 + d(i+1, j);
            int c = 1 + d(i, j+1);
            return h[{i,j}] = min(a, min(b, c));
        };
        return d(0,0);
    }
};

73. Set Matrix Zeroes

  • 為了不另開空間,第一行第一列先掃一遍,然后用來做記錄召嘶。
void setZeroes(int** matrix, int matrixRowSize, int matrixColSize) {
    int row = 1, col = 1;
    for(int i=0;i<matrixRowSize;i++)
        if(matrix[i][0]==0){
            col = 0;
            break;
        }
    for(int i=0; i<matrixColSize; i++)
        if(matrix[0][i]==0){
            row = 0;
            break;
        }
    for(int i=0;i<matrixRowSize;i++)
        for(int j=0; j<matrixColSize; j++)
            if(matrix[i][j]==0)
                matrix[i][0] = matrix[0][j] = 0;
    for(int i=1;i<matrixRowSize;i++)
        if(matrix[i][0]==0)
            for(int j=0;j<matrixColSize;j++)
                matrix[i][j] = 0;
    for(int i=1;i<matrixColSize;i++)
        if(matrix[0][i]==0)
            for(int j=0;j<matrixRowSize;j++)
                matrix[j][i] = 0;                
    if(row==0)
        for(int i=0; i<matrixColSize; i++)
            matrix[0][i] = 0;
    if(col==0)
        for(int i=0;i<matrixRowSize;i++)
            matrix[i][0] = 0;
}

74. Search a 2D Matrix

  • 二分查找
  • 這題直接按照一維就可以了父晶。
bool searchMatrix(int** matrix, int m, int n, int target) {
    int a = 0, b = m*n;
    while(a<b){
        int c = (a+b)/2;
        int mid = matrix[c/n][c%n];
        if(mid==target)
            return true;
        else if(mid<target)
            a = c + 1;
        else
            b = c;
    }
    return false;
}

75. Sort Colors

  • 題目要求不要用排序函數(shù)
  • 這道題正好只有三個(gè)元素要排序
    • 數(shù)組遍歷過程中往兩端插入
class Solution {
public:
    void sortColors(vector<int>& nums) {
        int l = 0, r = nums.size()-1;
        for(int i=l; i<=r;){
            switch(nums[i]){
                case 0:
                    swap(nums[i], nums[l++]);
                case 1:
                    i++;
                    break;
                case 2:
                    swap(nums[i], nums[r--]);
                    break;
            }
        }
    }
};

76. Minimum Window Substring

  • 雙指針
  • 收縮比擴(kuò)展好實(shí)現(xiàn)
class Solution {
public:
    string minWindow(string s, string t) {
        int start = 0;
        int size = INT_MAX;
        int h[128] = {0};
        for(char ch: t)
            h[ch]++;
        int d[128] = {0};
        int count = 0;
        for(int i=0, j=0;i<s.size(); i++){
            if(h[s[i]]){
                d[s[i]]++;
                if(d[s[i]]<=h[s[i]])
                    count++;
                if(count==t.size()){
                    while(d[s[j]]>h[s[j]] || h[s[j]]==0)
                        d[s[j++]]--;
                    if(i-j+1<size){
                        size = i-j+1;
                        start = j;
                    }
                }
            }
        }
        return size==INT_MAX ? "" : s.substr(start,size);
    }
};

77. Combinations

  • 排列組合問題,組合是全排列中升序的排列
  • 該題的序列是從 1 開始的
class Solution {
public:
    vector<vector<int>> combine(int n, int k) {
        vector<vector<int>> result;
        vector<int> item(k);
        function<void(int,int)> loop = [&](int i, int x){
            if(i==k){
                result.push_back(item);
                return;
            }
            for(int j=x;j<=n;j++){
                item[i] = j;
                loop(i+1,j+1);
            }
        };
        loop(0, 1);
        return result;
    }
};

78. Subsets

  • 排列組合問題
  • 二進(jìn)制位表示集合
class Solution {
public:
    vector<vector<int>> subsets(vector<int>& nums) {
        vector<vector<int>> result;
        for(int i=0, n=(1<<nums.size()); i<n; i++){
            vector<int> item;
            for(int j=0; j<nums.size(); j++)
                if((i>>j)&1)
                    item.push_back(nums[j]);
            result.push_back(item);
        }
        return result;
    }
};

79. Word Search

  • 圖的深度優(yōu)先搜索
  • 本題中要求路徑無環(huán)弄跌,矩陣按行儲(chǔ)存
bool f(char** board, int boardRowSize, int boardColSize, char* word,int x,int y,bool** visited) {
    if(*word==0)
        return true;
    if(x<0 || x>= boardColSize || y<0 || y>=boardRowSize)
        return false;
    if(visited[y][x])
        return false;
    if(board[y][x]==*word){
        visited[y][x] = true;
        bool result = (
            f(board, boardRowSize, boardColSize, word+1, x-1, y, visited)||
            f(board, boardRowSize, boardColSize, word+1, x+1, y, visited)||
            f(board, boardRowSize, boardColSize, word+1, x, y-1, visited)||
            f(board, boardRowSize, boardColSize, word+1, x, y+1, visited)
        );
        visited[y][x] = false;
        return result;
    }
    return false;
}
bool exist(char** board, int boardRowSize, int boardColSize, char* word) {
    bool **visited = (bool**)malloc(sizeof(bool*)*boardRowSize);
    for(int i=0;i<boardRowSize;i++)
        visited[i] = (bool*)calloc(1, sizeof(bool*)*boardColSize);
    for(int y=0; y<boardRowSize; y++)
        for(int x=0; x<boardColSize; x++)
            if(f(board, boardRowSize, boardColSize, word, x, y, visited))
                return true;
    return false;
}

80. Remove Duplicates from Sorted Array II

  • 有序數(shù)組,重復(fù)元素相鄰
int removeDuplicates(int* nums, int numsSize) {
    int *p = nums;
    int item = -1, count = 0;
    for(int i=0; i<numsSize; i++){
        if(nums[i]==item){
            if(count==2)
                continue;
            count++;
        }else{
            item = nums[i];
            count = 1;
        }
        *p++=nums[i];
    }
    return p - nums;
}

81. Search in Rotated Sorted Array II

Search

  • 二分搜索尝苇,旋轉(zhuǎn)后的有序數(shù)組
  • 比之前的題目多了:有重復(fù)元素
bool search(int* A, int n, int target) {
    int a = 0, b = n;
    while(a<b){
        int c = a+(b-a)/2;
        if(A[c]==target){
            return true;
        }else if(A[a]==A[c]){
            a++;
        }else if(A[a]<A[c]){
            if(A[a]<=target && target<A[c])
                b = c;
            else
                a = c + 1;
        }else{
            if(A[c]<target && target<=A[b-1])
                a = c + 1;
            else
                b = c;
        }
    }
    return false;  
}

82. Remove Duplicates from Sorted List II

  • 鏈表節(jié)點(diǎn)操作
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        ListNode** p = &head;
        while(*p){
            ListNode* q = (*p)->next; 
            if(q && q->val==(*p)->val){
                q = q->next;
                while(q && q->val==(*p)->val)
                    q = q->next;
                *p = q;
            }else
                p = &(*p)->next;
        }
        return head;
    }
};

83. Remove Duplicates from Sorted List

  • 前面有題目是數(shù)組铛只,這次是鏈表。
class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        for(auto p = head; p; p = p->next){
            auto q = p->next;
            while(q && q->val==p->val)
                q = q->next;
            p->next = q;
        }
        return head;
    }
};

84. Largest Rectangle in Histogram

  • 最大矩形
  • Stack糠溜,大于則入棧淳玩,小于則合并,最后合并全部非竿。
class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        int ans = 0;
        stack<int> s;
        heights.push_back(0);
        for(int i=0; i<heights.size();i++){
            while(!s.empty() && heights[i]<=heights[s.top()]){
                int j = s.top();
                s.pop();
                int width = s.empty() ? i : i-s.top()-1;
                ans = max(ans, heights[j]*width);
            }
            s.push(i);
        }
        return ans;
    }
};

85. Maximal Rectangle

  • 84. Largest Rectangle in Histogram 改改
  • 也可以用動(dòng)態(tài)規(guī)劃
class Solution {
public:
    int maximalRectangle(vector<vector<char>>& matrix) {
        int row = matrix.size();
        if(row==0)
            return 0;
        int col = matrix[0].size();
        vector<int> heights(col+1, 0);
        int ans = 0;
        for(int y=0;y<row; y++){
            for(int x=0; x<col; x++)
                heights[x] = matrix[y][x]=='1' ? heights[x] + 1 : 0;
            stack<int> s;
            for(int i=0; i<heights.size();i++){
                while(!s.empty() && heights[i]<=heights[s.top()]){
                    int j = s.top();
                    s.pop();
                    int width = s.empty() ? i : i-s.top()-1;
                    ans = max(ans, heights[j]*width);
                }
                s.push(i);
            }
        }
        return ans;
    }
};

86. Partition List

  • 鏈表節(jié)點(diǎn)操作
  • 鏈表追加蜕着,可以用一個(gè)空的頭節(jié)點(diǎn)
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
typedef struct ListNode Node;
void list_append(Node*** tail, Node* node){
    **tail = node;
    *tail = &node->next;
}
struct ListNode* partition(struct ListNode* head, int x) {
    Node* list1 = NULL;
    Node* list2 = NULL;
    Node** append1 = &list1;
    Node** append2 = &list2;
    for(; head; head=head->next)
        list_append(head->val<x ? &append1 : &append2, head);
    list_append(&append2, NULL);
    list_append(&append1, list2);
    return list1;
}

87. Scramble String

DP

  • 動(dòng)態(tài)規(guī)劃
class Solution {
public:
    bool isScramble(string s1, string s2) {
        map<tuple<int,int,int>,bool> m;
        function<bool(int,int,int)> f = [&](int a, int b, int c){
            //printf("%d %d %d\n",a,b,c);
            if(c==1)
                return s1[a]==s2[b];
            auto t = make_tuple(a, b, c);
            auto it = m.find(t);
            if(it!=m.end())
                return it->second;
            for(int i=1; i<c; i++){
                if(f(a,b,i) && f(a+i,b+i,c-i))
                    return m[t] = true;
                if(f(a,b+c-i,i) && f(a+i,b,c-i))
                    return m[t] = true;
            }
            return m[t] = false; 
        } ;
        if(s1.size()!=s2.size())
            return true;
        return f(0,0,s1.size());
    }
};

88. Merge Sorted Array

  • 有序數(shù)組歸并
  • 這題是在數(shù)組中插入另一個(gè)數(shù)組
void merge(int* nums1, int m, int* nums2, int n) {
    int* s = nums1 + m + n-1;
    int i = m-1, j = n-1;
    while(i>=0 && j>=0)
        *s-- = nums1[i] > nums2[j] ? nums1[i--] : nums2[j--];
    while(j>=0)
        *s-- = nums2[j--];
}

89. Gray Code

class Solution {
public:
    vector<int> grayCode(int n) {
        vector<int> ans;
        for(int i=0,e=1<<n; i<e; i++)
            ans.push_back((i>>1)^i);
        return ans;
    }
};

90. Subsets II

  • 遞歸 + 回溯
    • 或者自行用棧實(shí)現(xiàn)
  • 先統(tǒng)計(jì)重復(fù)元素個(gè)數(shù)
class Solution {
public:
    vector<vector<int>> subsetsWithDup(vector<int>& nums) {
        vector<vector<int>> result;
        unordered_map<int,int> h;
        for(int x: nums)
            h[x]++;
        vector<int> keys;
        for(auto p: h)
            keys.push_back(p.first);
        vector<int> stack;
        stack.push_back(-1);
        while(!stack.empty()){
            int n = stack.size();
            stack.back()++;
            if(stack.back()>h[keys[n-1]]){
                stack.pop_back();
            }else if(n==keys.size()){
                vector<int> item;
                for(int j=0; j<n; j++)
                    for(int k=0; k<stack[j]; k++)
                        item.push_back(keys[j]);
                result.push_back(item);
            }else{
                stack.push_back(-1);
            }
        }
        return result;
    }
};

91. Decode Ways

  • 回溯,動(dòng)態(tài)規(guī)劃
class Solution {
public:
    int numDecodings(string s) {
        int a = 1, b = 1, c = 0;
        char p = 0;
        for(char ch: s){
            c = 0;
            if(ch!='0')
                c += b;
            if((p=='2'&&ch<='6')||(p=='1'))
                c += a;
            p = ch;
            a = b;
            b = c;
        }
        return c;
    }
};

92. Reverse Linked List II

  • 挺有趣的一道題
  • 在逆置鏈表的基礎(chǔ)上改一下
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
    ListNode* reverse(ListNode* head){
        ListNode* prev = NULL;
        while(head){
            auto next = head->next;
            head->next = prev;
            prev = head;
            head = next;
        }
        return prev;
    }
public:
    ListNode* reverseBetween(ListNode* head, int m, int n) {
        ListNode** p = &head;
        for(int i=1; i<m; i++)
            p = &(*p)->next;
        ListNode* first = *p;
        ListNode* last = *p;
        for(int i=m; i<n; i++)
            last = last->next;
        ListNode* next = last->next;        
        last->next = NULL;
        *p = reverse(*p);
        first->next = next;
        return head;
    }
};

93. Restore IP Addresses

  • 回溯
class Solution {
public:
    vector<string> restoreIpAddresses(string s) {
        vector<string> result;
        vector<int> path;
        function<void(int,int)> f = [&](int i, int x){
            if(i==s.size()){
                if(path.size()==4 && x==0){
                    char b[s.size()+4];
                    sprintf(b,"%d.%d.%d.%d",path[0],path[1],path[2],path[3]);
                    result.push_back(b);
                }
                return;
            }
            int y = x*10 + (s[i]-'0');
            if(y>=256)
                return;
            if(y!=0)
                f(i+1, y);
            if(path.size()<4){
                path.push_back(y);
                f(i+1, 0);
                path.pop_back();
            }
        };
        f(0, 0);
        return result;
    }
};

94. Binary Tree Inorder Traversal

  • 重點(diǎn)問題红柱!
  • 二叉樹中序遍歷
    • LNR承匣,根節(jié)點(diǎn)在左右節(jié)點(diǎn)之間訪問
    • 對(duì)排序二叉樹樹得到升序序列
  • 遞歸,非遞歸
    • 先訪問最左邊的節(jié)點(diǎn)
    • 記錄出棧順序
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> s;
        TreeNode* p = root;
        while(p || !s.empty()){
            if(p){
                s.push(p);
                p = p->left;
            }else{
                p = s.top();
                s.pop();
                result.push_back(p->val);
                p = p->right;
            }
        }
        return result;
    }
};

95. Unique Binary Search Trees II

  • 挺有趣的題目
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
    vector<TreeNode*> generateTrees(int begin, int end) {
        vector<TreeNode*> result;
        if(begin==end)
            result.push_back(NULL);
        else
            for(int i=begin; i<end; i++)
                for(auto left: generateTrees(begin,i))
                    for(auto right: generateTrees(i+1, end)){
                        auto node = new TreeNode(i);
                        node->left = left;
                        node->right = right;
                        result.push_back(node);
                    }
        return result;
    }
public:
    vector<TreeNode*> generateTrees(int n) {
        if(n==0)
            return {};
        return generateTrees(1, n+1);
    }
};

96. Unique Binary Search Trees

  • 動(dòng)態(tài)規(guī)劃
  • 以上一題為基礎(chǔ)
  • 選一個(gè)根節(jié)點(diǎn)锤悄,個(gè)數(shù)為左子樹乘以右子樹韧骗,然后求和
class Solution {
public:
    int numTrees(int n) {
        vector<int> f(n+1);
        f[0] = f[1] = 1;
        for(int i=2; i<=n; i++)
            for(int j=1; j<=i; j++)
                f[i] += f[j-1]*f[i-j];
        return f[n];
    }
};

97. Interleaving String

DP

動(dòng)態(tài)規(guī)劃

class Solution {
public:
    bool isInterleave(string s1, string s2, string s3) {
        int l1 = s1.size();
        int l2 = s2.size();
        int l3 = s3.size();
        if(l1+l2!=l3)
            return false;
        vector<bool> d(l1+1);
        d[0] = true;
        for(int i=0; i<l1; i++)
            d[i+1] = d[i] && s1[i]==s3[i];
        for(int i=0; i<l2; i++){
            d[0] = d[0] && s2[i]==s3[i];
            for(int j=0; j<l1; j++){
                char c = s3[i+j+1];
                d[j+1] = (d[j] && s1[j]==c) || (d[j+1] && s2[i]==c);
            }
        }
        return d[l1];
    }
};

98. Validate Binary Search Tree

  • 檢查是否為二叉搜索樹
    • 節(jié)點(diǎn)滿足大小升序關(guān)系
  • 二叉樹中序遍歷
    • 遞歸,非遞歸實(shí)現(xiàn)
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
    int *prev;
    bool f(TreeNode* node){
        if(!node)
            return true;
        if(!f(node->left))
            return false;
        if(prev && *prev>=node->val)
            return false;
        prev = &node->val;
        if(!f(node->right))
            return false;
        return true;
    }
public:
    bool isValidBST(TreeNode* root) {
        prev = NULL;
        return f(root);
    }
};

99. Recover Binary Search Tree

  • 二叉樹搜索樹中序遍歷得到升序序列
  • 用遞歸不符合題目 O(1) 空間的目標(biāo)
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
    TreeNode* prev = NULL;
    TreeNode* broken = NULL;
    TreeNode* broken2 = NULL;
    bool f(TreeNode* node){
        if(!node)
            return false;
        if(f(node->left))
            return true;
        if(prev && prev->val>node->val){
            if(broken==NULL){
                broken = prev;
                broken2 = node;
            }else{
                broken2 = node;
                return true;
            }
        }
        prev = node;
        if(f(node->right))
            return true;
        return false;
    }
public:
    void recoverTree(TreeNode* root) {
        f(root);
        swap(broken->val, broken2->val);
    }
};

100. Same Tree

  • 二叉樹
  • 遞歸遍歷
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
bool isSameTree(struct TreeNode* p, struct TreeNode* q) {
    if(p && q)
        return (
            p->val == q->val && 
            isSameTree(p->left, q->left) &&
            isSameTree(p->right, q->right)
        );
    else
        return p==NULL && q==NULL;
}

101. Symmetric Tree

  • 題目要求兩種解法

遞歸

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
 
bool isMirror(struct TreeNode* t1, struct TreeNode* t2){
    if(!t1 && !t2)
        return true;
    if(!t1 || !t2)
        return false;
    if(t1->val!=t2->val)
        return false;
    return isMirror(t1->left, t2->right) && isMirror(t1->right, t2->left);
}
bool isSymmetric(struct TreeNode* root) {
    return root ? isMirror(root->left, root->right) : true;
}

迭代

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        if(!root)
            return true;
        stack<TreeNode*> q;
        q.push(root->left);
        q.push(root->right);
        while(!q.empty()){
            auto a = q.top();
            q.pop();
            auto b = q.top();
            q.pop();
            if(!a && !b)
                continue;
            if(!a || !b)
                return false;
            if(a->val!=b->val)
                return false;
            q.push(a->left);
            q.push(b->right);
            q.push(b->left);
            q.push(a->right);
        }
        return true;
    }
};

這題 LeetCode 目前給的答案不太好

102. Binary Tree Level Order Traversal

  • 二叉樹層次遍歷
  • 隊(duì)列零聚,廣度優(yōu)先
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> result;
        vector<int> line;
        queue<TreeNode*> q;
        q.push(root);
        q.push(NULL);
        for(;;){
            TreeNode* node = q.front();
            q.pop();
            if(node){
                line.push_back(node->val);
                if(node->left)
                    q.push(node->left);
                if(node->right)
                    q.push(node->right);
            }else{
                if(line.empty())
                    break;
                result.push_back(line);
                line.clear();
                q.push(NULL);
            }
        }
        return result;
    }
};

103. Binary Tree Zigzag Level Order Traversal

  • 二叉樹層次遍歷
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
        vector<vector<int>> result;
        queue<TreeNode*> q;
        bool r = false;
        if(root)
            q.push(root);
        while(!q.empty()){
            vector<int> item;
            int n = q.size();
            while(n--){
                auto node = q.front();
                q.pop();
                item.push_back(node->val);
                if(node->left)
                    q.push(node->left);
                if(node->right)
                    q.push(node->right);
            }
            if(r)
                reverse(item.begin(), item.end());
            result.push_back(item);
            r = !r;
        }
        return result;
    }
};

104. Maximum Depth of Binary Tree

  • 二叉樹遍歷
class Solution {
public:
    int maxDepth(TreeNode* root) {
        if(root==NULL)
            return 0;
        return 1 + max(maxDepth(root->left),maxDepth(root->right));        
    }
};

105. Construct Binary Tree from Preorder and Inorder Traversal

  • 二叉樹遍歷袍暴,逆
  • 遞歸
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        function<TreeNode*(int,int,int)> build = [&](int i, int j, int n)->TreeNode*{
            if(n==0)
                return nullptr;
            int val = preorder[i];
            int left_size = find(inorder.begin()+j,inorder.end(),val)-inorder.begin()-j;
            int right_size = n-left_size-1;
            cout<<val<<left_size<<right_size<<endl;
            auto node = new TreeNode(val);
            node->left = build(i+1, j, left_size);
            node->right = build(i+left_size+1, j+left_size+1, right_size);
            return node;
        };
        return build(0,0, preorder.size());
    }
};

106. Construct Binary Tree from Inorder and Postorder Traversal

  • 同上
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
int find(int *xs, int x){
    for(int i=0;;i++)
        if(xs[i]==x)
            return i;
}
struct TreeNode *build(int *inorder,int *postorder,int n){
    if(n==0)
        return NULL;
    int value = postorder[n-1];
    int left_length = find(inorder, value);
    int right_length = n - left_length - 1;
    struct TreeNode *node = (struct TreeNode*)malloc(sizeof(struct TreeNode));
    node->val = value;
    node->left = build(inorder, postorder, left_length);
    node->right = build(inorder+left_length+1, postorder+left_length, right_length);
    return node;
}
struct TreeNode* buildTree(int* inorder, int inorderSize, int* postorder, int postorderSize) {
    return build(inorder, postorder, inorderSize);
}

107. Binary Tree Level Order Traversal II

  • 二叉樹
  • 廣度優(yōu)先搜索,層次遍歷
  • 這題要求輸出逆序
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> levelOrderBottom(TreeNode* root) {
        vector<vector<int>> result;
        queue<TreeNode*> q;
        if(root)
            q.push(root);
        while(!q.empty()){
            int n = q.size();
            vector<int> item;
            while(n--){
                auto node = q.front();
                q.pop();
                item.push_back(node->val);
                if(node->left)
                    q.push(node->left);
                if(node->right)
                    q.push(node->right);
            }
            result.push_back(item);
        }
        reverse(result.begin(), result.end());
        return result;
    }
};

108. Convert Sorted Array to Binary Search Tree

  • 二分搜索
  • 遞歸隶症,構(gòu)建搜索樹
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
struct TreeNode* sortedArrayToBST(int* nums, int numsSize) {
    if(numsSize==0)
        return NULL;
    typedef struct TreeNode Node;
    Node* node = (Node*)malloc(sizeof(Node));
    node->val = nums[numsSize/2];
    node->left = sortedArrayToBST(nums, numsSize/2);
    node->right = sortedArrayToBST(nums+numsSize/2+1, numsSize-numsSize/2-1);
    return node;
}

109. Convert Sorted List to Binary Search Tree

  • 遞歸
  • 按中序遍歷從有序序列中取元素
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
    TreeNode* f(ListNode** node, int a, int b){
        if(a>=b)
            return NULL;
        int c = a+(b-a)/2;
        auto tree_node = new TreeNode(-1);
        tree_node->left = f(node, a, c);
        tree_node->val = (*node)->val;
        *node = (*node)->next;
        tree_node->right = f(node, c+1, b);
        return tree_node;
    }
public:
    TreeNode* sortedListToBST(ListNode* head) {
        int n = 0;
        for(auto p=head; p; p=p->next)
            n++;
        return f(&head, 0, n);
    }
};

110. Balanced Binary Tree

  • 遞歸+短路
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
    bool isBalanced(TreeNode* root, int* depth) {
        if(!root){
            *depth = 0;
            return true;
        }
        int left_depth, right_depth;
        if(!isBalanced(root->left, &left_depth))
            return false;
        if(!isBalanced(root->right, &right_depth))
            return false;
        if(abs(left_depth-right_depth)>1)
            return false;
        *depth = max(left_depth, right_depth)+1;
        return true;
    }    
public:
    bool isBalanced(TreeNode* root) {
        int depth;
        return isBalanced(root, &depth);
    }
};

111. Minimum Depth of Binary Tree

  • 二叉樹
  • 遞歸
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int minDepth(TreeNode* root) {
        if(root==nullptr)
            return 0;
        if(root->left==nullptr)
            return minDepth(root->right)+1;
        if(root->right==nullptr)
            return minDepth(root->left)+1;
        return min(minDepth(root->left), minDepth(root->right)) + 1;
    }
};

112. Path Sum

  • 二叉樹政模,短路
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
bool hasPathSum(struct TreeNode* root, int sum) {
    if(!root)
        return false;
    sum -= root->val;
    if(!root->left && !root->right)
        return sum==0;
    return hasPathSum(root->left, sum) || hasPathSum(root->right, sum);
}

113. Path Sum II

  • 二叉樹,葉節(jié)點(diǎn)蚂会,路徑
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> pathSum(TreeNode* root, int sum) {
        vector<vector<int>> result;
        vector<int> path;
        function<void(TreeNode*,int)> f = [&](TreeNode* node,int sum){
            if(!node)
                return;
            sum -= node->val;
            path.push_back(node->val);
            if(!node->left && !node->right){
                if(sum==0)
                    result.push_back(path);
            }else{
                f(node->left, sum);
                f(node->right, sum);
            }
            path.pop_back();
        };
        f(root, sum);
        return result;
    }
};

114. Flatten Binary Tree to Linked List

Tree

  • 先序
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
    TreeNode* f(TreeNode* node,TreeNode* tail){
        if(!node)
            return tail;
        node->right = f(node->left, f(node->right, tail));
        node->left = NULL;
        return node;
    }
public:
    void flatten(TreeNode* root) {
        f(root, NULL);
    }
};

115. Distinct Subsequences

  • 動(dòng)態(tài)規(guī)劃
  • 返回子序列個(gè)數(shù)
    • 遞歸前綴的部分
class Solution {
public:
    int numDistinct(string s, string t) {
        vector<int> d(t.size()+1, 0);
        d[0] = 1;
        for(int i=0; i<s.size(); i++)
            for(int j=t.size(); j>0; j--)
                if(s[i]==t[j-1])
                    d[j] += d[j-1];
        return d[t.size()];
    }
};

116. Populating Next Right Pointers in Each Node

  • 這題的輸入限定為滿二叉樹(最后一層也是滿的的完全二叉樹)淋样。
  • 題目要求不開空間,
/**
 * Definition for binary tree with next pointer.
 * struct TreeLinkNode {
 *  int val;
 *  TreeLinkNode *left, *right, *next;
 *  TreeLinkNode(int x) : val(x), left(NULL), right(NULL), next(NULL) {}
 * };
 */
class Solution {
public:
    void connect(TreeLinkNode *root) {
        if(!root)
            return;
        TreeLinkNode* next_level = root;
        for(TreeLinkNode* node;;){
            node = next_level;
            next_level = node->left;
            if(!next_level)
                break;
            TreeLinkNode* prev = NULL;
            while(node){
                if(prev)
                    prev->next = node->left;
                node->left->next = node->right;
                prev = node->right;
                node = node->next;
            }
        }
    }
};

117. Populating Next Right Pointers in Each Node II

  • 上一題的超集
/**
 * Definition for binary tree with next pointer.
 * struct TreeLinkNode {
 *  int val;
 *  TreeLinkNode *left, *right, *next;
 *  TreeLinkNode(int x) : val(x), left(NULL), right(NULL), next(NULL) {}
 * };
 */
class Solution {
public:
    void connect(TreeLinkNode *root) {
        TreeLinkNode *next_level = root;
        while(next_level){
            auto node = next_level;
            next_level = NULL;
            TreeLinkNode *prev = NULL;
            while(node){
                if(node->left){
                    if(prev)
                        prev->next = node->left;
                    if(!next_level)
                        next_level = node->left;
                    prev = node->left;
                }
                if(node->right){
                    if(prev)
                        prev->next = node->right;
                    if(!next_level)
                        next_level = node->right;
                    prev = node->right;
                }
                node = node->next;
            }
        }
    }
};

118. Pascal's Triangle

class Solution {
public:
    vector<vector<int>> generate(int numRows) {
        vector<vector<int>> result;
        if(numRows==0)
            return result;
        result.push_back({1});
        for(int i=1;i<numRows;i++){
            auto& last = result.back();
            vector<int> row(i+1);
            row[0] = 1;
            for(int j=0; j<i; j++)
                row[j+1] = last[j] + last[j+1];
            row[i] = 1;
            result.push_back(row);
        }
        return result;
    }
};

119. Pascal's Triangle II

class Solution {
public:
    vector<int> getRow(int rowIndex) {
        vector<int> row(rowIndex+1, 0);
        row[0] = 1;
        for(int i=0; i<rowIndex; i++)
            for(int j=i+1;j>0;j--)
                row[j] += row[j-1];
        return row;
    }
};

120. Triangle

  • 動(dòng)態(tài)規(guī)劃
class Solution {
public:
    int minimumTotal(vector<vector<int>>& triangle) {
        vector<int> d = triangle.back();
        for(int i=triangle.size()-2; i>=0; i--){
            for(int j=0; j<i+1; j++){
                d[j] = triangle[i][j] + min(d[j],d[j+1]);
            }
        }
        return d[0];
    }
};

121. Best Time to Buy and Sell Stock

  • 一次買颂龙,一次賣
    • 先買后賣习蓬,低買高賣
    • 遍歷序列,記錄當(dāng)前的最小值
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        if(prices.size()<=1)
            return 0;
        int lowest = prices[0], profit = 0;
        for(int x: prices){
            lowest = min(lowest, x);
            profit = max(x-lowest, profit);
        }
        return profit;
    }
};
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        if(prices.size()<=1)
            return 0;
        int lowest = INT_MAX, profit = 0;
        for(int x: prices){
            lowest = min(lowest, x);
            profit = max(x-lowest, profit);
        }
        return profit;
    }
};

122. Best Time to Buy and Sell Stock II

  • 要求買入前已經(jīng)賣出
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int profit = 0;
        for(int i=1; i<prices.size(); i++)
            profit += max(prices[i]-prices[i-1], 0);
        return profit;
    }
};

123. Best Time to Buy and Sell Stock III

  • 最多兩次交易
  • 前后掃兩趟措嵌,分治
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int n = prices.size();
        if(n<=1)
            return 0;
        vector<int> profit1(n, 0);
        vector<int> profit2(n, 0);
        int lowest = prices[0];
        for(int i=1; i<n; i++){
            lowest = min(lowest, prices[i]);
            profit1[i] = max(prices[i]-lowest, profit1[i-1]);
        }
        cout<<profit1[n-1]<<lowest<<endl;
        int highest = prices[n-1];
        for(int i=n-2; i>=0; i--){
            highest = max(highest, prices[i]);
            profit2[i] = max(highest-prices[i], profit2[i+1]);
        }
        cout<<profit2[0]<<highest<<endl;
        int profit = INT_MIN;
        for(int i=0; i<n; i++){
            profit = max(profit, profit1[i]+profit2[i]);
        }
        return profit;
    }
};

124. Binary Tree Maximum Path Sum

  • 加正數(shù)會(huì)變大
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
    int ans = INT_MIN;
    int f(TreeNode* node){
        if(node){
            int val = node->val;
            int left = max(f(node->left), 0);
            int right = max(f(node->right), 0);
            ans = max(ans, left+right+val);
            return max(left,right)+val;
        }else{
            return 0;
        }
    }
public:
    int maxPathSum(TreeNode* root) {
        f(root);
        return ans;
    }
};

125. Valid Palindrome

class Solution {
public:
    bool isPalindrome(string s) {
        if(s.empty())
            return true;
        for(int i=0, j=s.size()-1;;i++,j--){
            while(!isalnum(s[i]))
                i++;
            while(!isalnum(s[j]))
                j--;
            if(i>=j)
                break;
            if(toupper(s[i])!=toupper(s[j]))
                return false;                
        }
        return true;
    }
};

126. Word Ladder II

class Solution {
    template<class Callback>
    inline void transform(string word,Callback callback){
        for(int i=0; i<word.size(); i++){
            char c = word[i];
            for(char j='a';j<='z';j++){
                if(j!=c){
                    word[i] = j;
                    callback(word);
                }
            }
            word[i] = c;
        }        
    }
public:
    vector<vector<string>> findLadders(string beginWord, string endWord, unordered_set<string> &wordList) {
        unordered_map<string,int> dist;
        unordered_map<string,vector<string>> path;
        queue<string> q;
        q.push(beginWord);
        dist[beginWord] = 1;
        while(!q.empty()){
            auto x = q.front();
            q.pop();
            cout<<x<<endl;
            if(x==endWord)
                break;
            transform(x, [&](const string& word){
                if(wordList.count(word)){
                    if(dist[word]==0){
                        dist[word] = dist[x]+1;
                        q.push(word);
                    }
                    if(dist[word]==dist[x]+1)
                        path[word].push_back(x);
                }
            });
        }
        vector<vector<string>> result;
        vector<string> item;
        function<void(const string&)> buildPath = [&](const string& node){
            if(node==beginWord){
                auto item2 = item;
                item2.push_back(node);
                reverse(begin(item2),end(item2));
                result.push_back(item2);
                return;
            }
            item.push_back(node);
            for(auto& s:path[node])
                buildPath(s);
            item.pop_back();
        };
        buildPath(endWord);
        return result;        
    }
};

127. Word Ladder

  • 圖論躲叼,廣度優(yōu)先搜索
    • 用隊(duì)列實(shí)現(xiàn)
  • 這題給個(gè)測(cè)試用例單詞很短,但是單詞數(shù)量很多
    • 比如說有個(gè) 5 的字符長(zhǎng)度(5*25=125個(gè)變換)企巢,2370 個(gè)單詞的
    • 這種情況下用字符串兩兩比較會(huì)超時(shí)
class Solution {
    bool adjacent(const string& s1, const string& s2){
        if(s1.size()!=s2.size())
            return false;
        int count = 0;
        for(int i=0; i<s1.size() && count<2; i++){
            if(s1[i]!=s2[i])
                count++;
        }
        return count==1;
    }
public:
    int ladderLength(string beginWord, string endWord, unordered_set<string>& wordList) {
        unordered_map<string,int> dist;
        queue<string> q;
        q.push(beginWord);
        dist[beginWord] = 1;
        while(!q.empty()){
            auto x = q.front();
            q.pop();
            if(x==endWord)
                break;
            string o = x;
            for(int i=0; i<x.size(); i++){
                char c = x[i];
                for(char j='a';j<='z';j++){
                    if(j!=c){
                        x[i] = j;
                        if(wordList.count(x) && !dist[x]){
                            q.push(x);
                            dist[x] = dist[o]+1;
                        }
                    }
                }
                x[i] = c;
            }
            // for(auto v: wordList){
            //     if(!dist[v] && adjacent(x,v)){
            //         q.push(v);
            //         dist[v] = dist[x]+1;
            //     }
            // }
        }
        return dist[endWord];
    }
};

128. Longest Consecutive Sequence

  • 要求 O(N)
class Solution {
    unordered_map<int,int> h;
    int ds_find(int x){
        if(h[x]!=x)
            h[x] = ds_find(h[x]);
        return h[x];
    }
    void ds_union(int x, int y){
        h[ds_find(x)] = ds_find(y);
    }
public:
    int longestConsecutive(vector<int>& nums) {
        for(int x: nums)
            h[x] = x;
        for(int x: nums){
            if(h.count(x+1))
                ds_union(x, x+1);
            if(h.count(x-1))
                ds_union(x, x-1);
        }
        unordered_map<int,int> a;
        for(auto p: h)
            a[ds_find(p.second)]++;
        int ans = 0;
        for(auto p: a)
            ans = max(ans, p.second);
        return ans;
    }
};

129. Sum Root to Leaf Numbers

  • 二叉樹
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int sumNumbers(TreeNode* root) {
        function<int(TreeNode*,int)> f = [&](TreeNode* node,int num){
            if(!node)
                return 0;
            num = num*10 + node->val;
            if(!node->left && !node->right)
                return num;
            return f(node->left, num)+f(node->right, num);
        };
        return f(root, 0);
    }
};

130. Surrounded Regions

  • 遞歸會(huì)爆棧枫慷,
    • LeetCode 顯示 RunTime Error
class Solution {
public:
    void solve(vector<vector<char>>& board) {
        int m = board.size();
        if(m==0)
            return;
        int n = board[0].size();
        function<void(int,int)> f = [&](int x, int y){
            if(board[y][x]=='O'){
                board[y][x] = 'T';
                if(y+1 < m-1)
                    f(x, y+1);
                if(y-1 > 0)
                    f(x, y-1);
                if(x+1 < n-1)
                    f(x+1, y);
                if(x-1 > 0)
                    f(x-1, y);
            }
        };
        for(int i=0; i<n; i++){
            f(i, 0);
            f(i, m-1);
        }
        for(int j=0; j<m; j++){
            f(0, j);
            f(n-1, j);
        }
        for(auto& xs: board)
            for(auto& x: xs)
                if(x=='O')
                    x = 'X';
                else if(x=='T')
                    x = 'O';
    }
};

131. Palindrome Partitioning

Backtracking

  • 深度優(yōu)先搜索
  • 動(dòng)態(tài)規(guī)劃
class Solution {
    bool  isPalindrome(const string& s, int start, int last){
        while(start<last){
            if(s[start]!=s[last])
                return false;
            start++, last--;
        }
        return true;
    }
public:
    vector<vector<string>> partition(string s) {
        vector<vector<string>> result;
        //unordered_map<string,vector<string>> h;
        vector<string> path;
        function<void(int)> f = [&](int i){
            if(i==s.size()){
                result.push_back(path);
                return;
            }
            for(int j=i; j<s.size(); j++){
                if(isPalindrome(s,i,j)){
                    path.push_back(s.substr(i,j-i+1));
                    f(j+1);
                    path.pop_back();
                }
            }
        };
        f(0);
        return result;
    }
};

132. Palindrome Partitioning II

  • 求最小割數(shù)
  • 長(zhǎng)度 n 最多 n-1 個(gè)割
  • 一個(gè)字串可以遞歸分解為一個(gè)回文子串和另一個(gè)字串
class Solution {
public:
    int minCut(string s) {
        int n = s.size();
        vector<int> c(n+1);
        vector<vector<bool>> d(n,vector<bool>(n));
        for(int i=0; i<=n; i++)
            c[i] = i - 1;
        for(int i=0; i<n; i++)
            for(int j=i; j>=0; j--)
                if(s[j]==s[i] && (i-j<3 || d[j+1][i-1])){
                    d[j][i] = true;
                    c[i+1] = min(c[i+1], c[j]+1);
                }
        return c[n];
    }
};
class Solution {
public:
    int minCut(string s) {
        int n = s.size();
        vector<int> c(n+1);
        vector<vector<bool>> d(n,vector<bool>(n));
        for(int i=0; i<=n; i++)
            c[i] = i - 1;
        for(int i=0; i<n; i++)
            for(int j=0; j<=i; j++)
                if(s[j]==s[i] && (i-j<3 || d[j+1][i-1])){
                    d[j][i] = true;
                    c[i+1] = min(c[i+1], c[j]+1);
                }
        return c[n];
    }
};

133. Clone Graph

  • 哈希表
  • 遞歸
/**
 * Definition for undirected graph.
 * struct UndirectedGraphNode {
 *     int label;
 *     vector<UndirectedGraphNode *> neighbors;
 *     UndirectedGraphNode(int x) : label(x) {};
 * };
 */
class Solution {
public:
    UndirectedGraphNode *cloneGraph(UndirectedGraphNode *node) {
        unordered_map<UndirectedGraphNode*,UndirectedGraphNode*> h;
        function<UndirectedGraphNode*(UndirectedGraphNode*)> f = [&](UndirectedGraphNode* node){
            auto it = h.find(node);
            if(it!=h.end())
                return it->second;
            auto new_node = new UndirectedGraphNode(node->label);
            h[node] = new_node;
            for(auto e: node->neighbors)
                new_node->neighbors.push_back(f(e));
            return new_node;
        };
        return node ? f(node) : nullptr;
    }
};

134. Gas Station

  • 一趟
  • 有兩個(gè)目標(biāo)
    1. 判斷是否能完成
    2. 尋找起點(diǎn)
class Solution {
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        int a = 0, d = 0;
        int start = 0;
        for(int i=0; i<gas.size(); i++){
            d += gas[i] - cost[i];
            if(d<0){
                a += d;
                d = 0;
                start = i+1;
            }
        }
        return a+d>=0 ? start : -1;
    }
};

135. Candy

  • 記錄變化量
int candy(int* ratings, int ratingsSize) {
    int a, *d = (int*)calloc(ratingsSize,sizeof(int));
    a = 1;
    for(int i=1; i<ratingsSize; i++){
        if(ratings[i] > ratings[i-1]){
            if(d[i]<a)
                d[i] = a;
            a++;
        }else{
            a = 1; 
        }
    }
    a = 1;
    for(int i=ratingsSize-2; i>=0; i--){
        if(ratings[i] > ratings[i+1]){
            if(d[i]<a)
                d[i] = a;
            a++;
        }else{
            a = 1;
        }
    }
    int sum = ratingsSize;
    for(int i=0; i<ratingsSize; i++){
        sum += d[i];
    }
    return sum;
}

136. Single Number

  • 整數(shù)的位運(yùn)算
  • 異或運(yùn)算,和零異或?yàn)樽约海妥约寒惢驗(yàn)?0
int singleNumber(int* nums, int numsSize) {
    int x = 0;
    for(int i=0; i<numsSize; i++)
        x ^= nums[i];
    return x;
}

137. Single Number II

  • 二進(jìn)制位加法
    • 異或運(yùn)算得到值或听,與運(yùn)算得到進(jìn)位
  • 本題得到 0b11 時(shí)再取模
class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int a=0, b=0;
        for(int x: nums){
            b ^= a&x;
            a ^= x;
            int c = ~(a&b);
            a &= c;
            b &= c;
        }
        return a;
    }
};

138. Copy List with Random Pointer

  • 圖的復(fù)制
/**
 * Definition for singly-linked list with a random pointer.
 * struct RandomListNode {
 *     int label;
 *     struct RandomListNode *next;
 *     struct RandomListNode *random;
 * };
 */
struct RandomListNode *copyRandomList(struct RandomListNode *head) {
    typedef struct RandomListNode Node;
    if(!head)
        return NULL;
    for(Node* node=head; node;){
        Node* copy = (Node*)malloc(sizeof(Node));
        *copy = *node;
        node->next = copy;
        node = copy->next;
    }
    for(Node* node=head; node;){
        Node* copy = node->next;
        if(copy->random)
            copy->random = copy->random->next;
        node = copy->next;
    }
    Node *head2 = head->next;
    for(Node *node = head; node;){
        Node *node2 = node->next;
        Node *next = node2->next;
        node->next = next;
        node2->next = next ? next->next : NULL;
        node = next;
    }
    return head2;
}
/**
 * Definition for singly-linked list with a random pointer.
 * struct RandomListNode {
 *     int label;
 *     RandomListNode *next, *random;
 *     RandomListNode(int x) : label(x), next(NULL), random(NULL) {}
 * };
 */
class Solution {
public:
    RandomListNode *copyRandomList(RandomListNode *head) {
        unordered_map<RandomListNode*,RandomListNode*> h;
        auto get = [&](RandomListNode* node)->RandomListNode*{
            if(!node)
                return NULL;
            auto it = h.find(node);
            if(it!=h.end())
                return it->second;
            else{
                return h[node] = new RandomListNode(node->label);
            }
        };
        for(auto p=head; p; p=p->next){
            auto node_clone = get(p);
            node_clone->random = get(p->random);
            node_clone->next = get(p->next);
        }
        return h[head];
    }
};

139. Word Break

  • 動(dòng)態(tài)規(guī)劃
  • 分詞/遞歸
class Solution {
public:
    bool wordBreak(string s, vector<string>& wordDict) {
        unordered_set<string> dict;
        for(auto& x: wordDict)
            dict.insert(x);
        vector<bool> d(s.size()+1, false);
        d[0] = true;
        for(int i=1;i<=s.size();i++)
            for(int j=i-1;j>=0;j--)
                if(d[j] && dict.count(s.substr(j, i-j))){
                    d[i] = true;
                    break;
                }
        return d.back();
    }
};
class Solution {
public:
    bool wordBreak(string s, vector<string>& wordDict) {
        unordered_set<string> dict;
        int len = 0;
        for(auto& x: wordDict){
            dict.insert(x);
            len = max(len,(int)x.size());
        }
        unordered_map<int,bool> m;
        function<bool(int)> f = [&](int i){
            if(i==s.size())
                return true;
            auto it = m.find(i);
            if(it!=m.end())
                return it->second;
            for(int j=i+1; j<=s.size() && j-i<=len; j++)
                if(dict.count(s.substr(i,j-i)) && f(j))
                    return m[i] = true;
            return m[i] = false;
        };
        return f(0);
    }
};

140. Word Break II

class Solution {
public:
    vector<string> wordBreak(string s, vector<string>& wordDict) {
        unordered_set<string> dict;
        for(auto& x: wordDict)
            dict.insert(x);
        int n = s.size();
        vector<vector<int>> edge(n+1,vector<int>());
        edge[0].push_back(0);
        for(int i=1; i<=n; i++)
            for(int j=i-1; j>=0; j--)
                if(edge[j].size() && dict.count(s.substr(j, i-j))){
                    edge[i].push_back(j);
                    printf("(%d->%d)\n",j,i);
                }
        vector<string> result;
        vector<string> path;
        function<void(int)> f = [&](int i){
            if(i==0){
                string item;
                for(int j=path.size()-1; j>=0; j--){
                    item += path[j];
                    item += ' ';
                }
                item.pop_back();
                result.push_back(item);
                return;
            }
            for(auto j: edge[i]){
                path.push_back(s.substr(j, i-j));
                f(j);
                path.pop_back();
            }
        };
        f(n);
        return result;
    }
};

141. Linked List Cycle

  • 鏈表探孝,雙指針
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    bool hasCycle(ListNode *head) {
        auto fast = head, slow = head;
        while(fast && fast->next){
            fast = fast->next->next;
            slow = slow->next;
            if(fast==slow)
                return true;
        }
        return false;
    }
};

142. Linked List Cycle II

List

  • 鏈表
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        auto fast = head, slow = head;
        while(fast && fast->next){
            fast = fast->next->next;
            slow = slow->next;
            if(fast==slow){
                auto node = head;
                while(node!=slow){
                    slow = slow->next;
                    node = node->next;
                }
                return node;
            }
        }
        return NULL;        
    }
};

143. Reorder List

  • 鏈表
  • 原地逆置+鏈表合并+快慢雙指針
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
    ListNode* nreverse(ListNode* head){
        ListNode* prev = NULL;
        while(head){
            auto next = head->next;
            head->next = prev;
            prev = head;
            head = next;
        }
        return prev;
    }
    void merge(ListNode* head1,ListNode* head2){
        while(head2){
            auto next1 = head1->next;
            auto next2 = head2->next;
            head1->next = head2;
            head2->next = next1;
            head1 = next1;
            head2 = next2;
        }
    }
    ListNode* cut(ListNode* head){
        auto fast = head, slow = head;
        while(fast && fast->next){
            fast = fast->next->next;
            slow = slow->next;
        }
        auto head2 = slow->next;
        slow->next = NULL;
        return head2;
    }
public:
    void reorderList(ListNode* head) {
        if(head)
            merge(head,nreverse(cut(head)));
    }
};

144. Binary Tree Preorder Traversal

  • 重點(diǎn)問題!
  • 二叉樹先序遍歷
    • NLR誉裆,先訪問根節(jié)點(diǎn)
  • 遞歸顿颅,非遞歸實(shí)現(xiàn)
    • 出棧順序
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> s;
        if(root)
            s.push(root);
        while(!s.empty()){
            TreeNode* node = s.top();
            s.pop();
            result.push_back(node->val);
            if(node->right)
                s.push(node->right);
            if(node->left)
                s.push(node->left);
        }
        return result;
    }
};

145. Binary Tree Postorder Traversal

Tree

  • 二叉樹后序遍歷的迭代實(shí)現(xiàn)
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> s;
        TreeNode *p = root;
        TreeNode *q = NULL;
        for(;;){
            if(p){
                s.push(p);
                p = p->left;
            }else if(!s.empty()){
                p = s.top();
                if(q==p->right || !p->right){
                    result.push_back(p->val);
                    q = p;
                    s.pop();
                    p = NULL;
                }else{
                    p = p->right;
                }
            }else{
                break;
            }
        }
        return result;
    }
};

146. LRU Cache

  • 需要在 O(1) 時(shí)間找到鏈表中的節(jié)點(diǎn)并移動(dòng)到頭部
    • 利用雙向鏈表和哈希表
    • c++ 的 splice 用來把另一個(gè)鏈表中的元素插入該位置前
class LRUCache{
    int capacity;
    unordered_map<int,list<pair<int,int>>::iterator> h;
    list<pair<int,int>> l;
public:
    LRUCache(int capacity) {
        this->capacity = capacity;
    }
    
    int get(int key) {
        auto it = h.find(key);
        if(it==h.end())
            return -1;
        l.splice(l.begin(), l, it->second);
        return it->second->second;
    }
    
    void set(int key, int value) {
        auto it = h.find(key);
        if(it!=h.end()){
            it->second->second = value;
            l.splice(l.begin(), l, it->second);
        }else{
            if(l.size()==capacity){
                h.erase(l.back().first);
                l.pop_back();
            }
            l.push_front(make_pair(key, value));
            h[key] = l.begin(); 
        }
    }
};

147. Insertion Sort List

  • 數(shù)組一般從后往前插
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* insertionSortList(ListNode* head) {
        ListNode* list = NULL;
        auto node = head;
        while(node){
            auto next = node->next;
            auto p = &list;
            while(*p && node->val > (*p)->val)
                p = &(*p)->next;
            node->next = *p;
            *p = node;
            node = next;
        }
        return list;
    }
};

148. Sort List

  • 鏈表
  • 歸并排序
  • 結(jié)合前面的題目
    • 21. Merge Two Sorted Lists,直接搬過來遞歸使用
    • 143. Reorder List足丢,那題有兩個(gè)節(jié)點(diǎn)的話不用斷開粱腻,這題要。
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
    ListNode* cut(ListNode* head){
        auto fast = head, slow = head;
        while(fast && fast->next && fast->next->next){
            fast = fast->next->next;
            slow = slow->next;
        }
        auto head2 = slow->next;
        slow->next = NULL;
        return head2;
    }
    ListNode* nmerge(ListNode* head1,ListNode* head2){
        ListNode* head = NULL;
        ListNode** append = &head; 
        for(;;){
            if(!head1){
                *append = head2;
                break;
            }
            if(!head2){
                *append = head1;
                break;
            }
            if(head1->val < head2->val){
                *append = head1;
                head1 = head1->next;
            }else{
                *append = head2;
                head2 = head2->next;
            }
            append = &(*append)->next;
        }
        return head;
    }
public:
    ListNode* sortList(ListNode* head) {
        if(!head || !head->next)
            return head;
        auto head2 = cut(head);
        return nmerge(sortList(head),sortList(head2));
    }
};

149. Max Points on a Line

  • 注意出現(xiàn)重合的點(diǎn)的情況
    • [[1,1],[1,1],[1,1]]
  • 該題的坐標(biāo)是整數(shù)
/**
 * Definition for a point.
 * struct Point {
 *     int x;
 *     int y;
 *     Point() : x(0), y(0) {}
 *     Point(int a, int b) : x(a), y(b) {}
 * };
 */
class Solution {
public:
    int maxPoints(vector<Point>& points) {
        int n = points.size();
        if(n<=2)
            return points.size();
        int m = 2;
        for(int i=0; i<n; i++){
            int start = 2;
            for(int j=i+1; j<n-1; j++){
                int dx = points[j].x-points[i].x;
                int dy = points[j].y-points[i].y;
                if(dx==0 && dy==0){
                    start++;
                    continue;
                }
                int bdx = dx*points[i].y - dy*points[i].x; 
                int count = start;
                for(int k=j+1; k<n; k++){
                    if(dx==0){
                        if(points[k].x == points[j].x)
                                count++;
                    }else{
                        if(dx*points[k].y==dy*points[k].x+bdx)
                                count++;
                    }
                }
                m = max(m, count);
            }
            m = max(m, start);
        }
        return m;
    }
};

150. Evaluate Reverse Polish Notation

  • Stack
int evalRPN(char** tokens, int tokensSize) {
    int size = 3;
    int* stack = (int*)malloc(sizeof(int)*size);
    int *p = stack;
    for(int i=0; i<tokensSize; i++){
        char *token = tokens[i];
        if(token[0] && !token[1]){
            switch(token[0]){
                case '+':
                    p[-2] += p[-1];
                    p--;
                    continue;
                case '-':
                    p[-2] -= p[-1];
                    p--;
                    continue;
                case '*':
                    p[-2] *= p[-1];
                    p--;
                    continue;
                case '/':
                    p[-2] /= p[-1];
                    p--;
                    continue;
            }
        }
        if(p-stack==size){
            stack = realloc(stack,sizeof(int)*(size*2));
            p = stack+size;
            size *= 2;
        }
        *p++ = atoi(token);
    }
    int ans = p[-1];
    free(stack);
    return ans;
}

151. Reverse Words in a String

Application

  • 逆置
  • 原地斩跌,一趟绍些。
class Solution {
    void reverse(string& s, int i, int j){
        while(i<j)
            swap(s[i++],s[j--]);
    }
    void compact(string& s){
        int k = 0;
        for(int i=0; i<s.size(); i++)
            if(s[i]!=' '){
                if(k!=0)
                    s[k++] = ' ';
                int j = i;
                while(j<s.size() && s[j]!=' ')
                    s[k++] = s[j++];
                i = j;
            }
        s.resize(k);
    }
public:
    void reverseWords(string &s) {
        compact(s);
        ::reverse(s.begin(), s.end());
        int start = 0;
        while(start<s.size() && s[start]==' ')
            start++;
        for(int i=0; i<s.size(); i++){
            if(s[i]==' '){
                reverse(s, start, i-1);
                start = i+1;
            }
        }
        reverse(s, start, s.size()-1);
    }
};

152. Maximum Product Subarray

  • 積最大
  • 正負(fù)
class Solution {
public:
    int maxProduct(vector<int>& nums) {
        int m = INT_MIN;
        int a = 1, b = 1;
        for(int x: nums){
            int c = max(x, max(a*x, b*x));
            b = min(x, min(a*x, b*x));
            m = max(m, c);
            a = c;
        }
        return m;
    }
};

153. Find Minimum in Rotated Sorted Array

這個(gè)解答有問題。耀鸦。柬批。

class Solution {
public:
    int findMin(vector<int>& nums) {
        int a = 0, b = nums.size();
        while(a<b){
            int c = (a+b-1)/2;
            if(nums[a]<=nums[b-1]){
                return nums[a];
            }else if(nums[c]>nums[b-1]){
                a = c + 1;
            }else{
                b = c + 1;
            }
        }
        return INT_MIN;
    }
};

154. Find Minimum in Rotated Sorted Array II

  • 有重復(fù)元素
class Solution {
public:
    int findMin(vector<int>& nums) {
        int a = 0, b = nums.size()-1;
        while(a<b){
            int c = (a+b)/2;
            if(nums[a]<nums[b])
                break;
            else if(nums[c]>nums[b])
                a = c + 1;
            else if(nums[a]>nums[c])
                b = c;
            else
                a++;
        }
        return nums[a];
    }
};
 
class Solution {
public:
    int findMin(vector<int>& nums) {
        int a = 0, b = nums.size();
        while(b-a>1){
            int c = (a+b-1)/2;
            if(nums[a]<nums[b-1])
                break;
            else if(nums[c]>nums[b-1])
                a = c + 1;
            else if(nums[a]>nums[c])
                b = c + 1;
            else
                a++;
        }
        return nums[a];
    }
};

155. Min Stack

  • 棧,先進(jìn)先出
  • 用另一個(gè)棧記錄最小元素
  • STL 中空棧取元素是未定義行為
class MinStack {
    stack<int> _stack;
    stack<int> _stack_min;
public:
    /** initialize your data structure here. */
    MinStack() {
        
    }
    
    void push(int x) {
        _stack.push(x);
        if(_stack_min.empty() || x<=_stack_min.top())
            _stack_min.push(x);
    }
    
    void pop() {
        int x = _stack.top();
        _stack.pop();
        if(!_stack_min.empty() && x==_stack_min.top())
            _stack_min.pop();
    }
    
    int top() {
        return _stack.top();
    }
    
    int getMin() {
        return _stack_min.top();
    }
};

/**
 * Your MinStack object will be instantiated and called as such:
 * MinStack obj = new MinStack();
 * obj.push(x);
 * obj.pop();
 * int param_3 = obj.top();
 * int param_4 = obj.getMin();
 */

160. Intersection of Two Linked Lists

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
    int list_length(ListNode* head){
        int n=1;
        while(head){
            n++;
            head = head->next;
        }
        return n;
    }
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        int lenA = list_length(headA);
        int lenB = list_length(headB);
        if(lenA>lenB){
            for(int i=lenA-lenB; i>0; i--)
                headA = headA->next;
        }else{
            for(int i=lenB-lenA; i>0; i--)
                headB = headB->next;
        }
        while(headA!=headB){
            headA = headA->next;
            headB = headB->next;
        }
        return headA;
    }
};

162. Find Peak Element

  • 二分查找
  • 找極大值
  • 越界為負(fù)無窮
class Solution {
public:
    int findPeakElement(vector<int>& nums) {
        auto less = [&](int i, int j){
            if(i==-1 || i==nums.size())
                return true;
            if(j==-1 || j==nums.size())
                return false;
            return nums[i] < nums[j];  
        };
        int a = 0, b = nums.size();
        while(a<b){
            int c = (a+b)/2;
            if(less(c-1,c) && less(c, c+1))
                a = c + 1;
            else if(less(c+1, c) && less(c, c-1))
                b = c;
            else if(less(c+1, c) && less(c-1, c))
                return c;
            else
                b = c;
        }
        return -1;
    }
};

164. Maximum Gap

Sort

  • 先排序 O(N)袖订,后查找 O(N)
//http://zh.wikipedia.org/zh-cn/%E5%9F%BA%E6%95%B0%E6%8E%92%E5%BA%8F
void radixsort(int data[], int n){
    int m = 0;
    for(int i=0;i<n;i++)
        if(data[i]>m)
            m = data[i];
    int *tmp = (int*)malloc(sizeof(int)*n);
    memset(tmp, 0, sizeof(int)*n);
    int count[10] = {0};
    for(unsigned radix=1;radix<=m;radix*=10){
        for(int i=0;i<10;i++)
            count[i] = 0;
        for(int i=0; i<n; i++)
            count[(data[i]/radix)%10]++;
        for(int i=1; i<10; i++)
            count[i] += count[i-1];
        for(int i=n-1; i>=0; i--)
            tmp[--count[(data[i]/radix)%10]] = data[i];
        for(int i=0; i<n; i++)
            data[i] = tmp[i];
    }
    free(tmp);
}
int maximumGap(int num[], int n) {
    if(n<2)
        return 0;
    radixsort(num,n);
    int pred = num[0];
    int max = 0;
    for(int i=1;i<n;i++){
        int curr = num[i];
        int delta = curr>pred ? curr-pred : pred-curr;
        if(delta>max)
            max = delta;
        pred = curr;
    }
    return max;
}

165. Compare Version Numbers

int compareVersion(char* version1, char* version2) {
    while(*version1 || *version2){
        int a = strtol(version1,&version1,10);
        int b = strtol(version2,&version2,10);
        if(*version1=='.')version1++;
        if(*version2=='.')version2++;
        if(a<b)return -1;
        if(a>b)return 1;
    }
    return 0;
}

166. Fraction to Recurring Decimal

class Solution {
    void append(string& s, unsigned n){
        stringstream ss;
        ss << n;
        s += ss.str();         
    }
public:
    string fractionToDecimal(int numerator, int denominator) {
        string s;
        if(numerator==0)
            return "0";
        if((numerator^denominator)&(1<<31))
             s += "-";
        long long a = llabs((long long)numerator), b = llabs((long long)denominator);
        append(s, a/b); 
        a %= b;
        if(a!=0){
            s.push_back('.');
            unordered_map<unsigned,int> h;
            for(int i=s.size(); a; i++){
                if(h.count(a)){
                    s.insert(h[a], "(");
                    s.push_back(')');
                    break;
                }
                h[a] = i;
                a *= 10;
                append(s, a/b);
                a %= b;
            }
        }
        return s;
    }
};

167. Two Sum II - Input array is sorted

  • 這題沒意思
class Solution {
public:
    vector<int> twoSum(vector<int>& numbers, int target) {
        int i = 0, j = numbers.size()-1;
        while(i<j){
            int s = numbers[i] + numbers[j];
            if(s==target)
                return {i+1, j+1};
            else if(s<target)
                i++;
            else
                j--;
        }
        return {0,0};
    }
};

168. Excel Sheet Column Title

class Solution {
public:
    string convertToTitle(int n) {
        string s;
        while(n){
            n--;
            s += 'A'+ n%26;
            n /= 26;
        }
        reverse(s.begin(), s.end());
        return s;
    }
};

169. Majority Element

  • 數(shù)組老題氮帐,題干有若干假設(shè)
int majorityElement(int* nums, int numsSize) {
    int x = nums[0];
    int count = 1;
    for(int i=1; i<numsSize; i++){
        if(nums[i]==x){
            count++;
        }else{
            count--;
            if(count==0){
                x = nums[i];
                count=1;
            }
        }
    }
    return x;
}

171. Excel Sheet Column Number

int titleToNumber(char* s) {
    int n = 0;
    for(;*s;s++)
        n = n*26+*s-'A'+1;
    return n;
}

172. Factorial Trailing Zeroes

索引:整數(shù)

  • 求區(qū)間上因子5的個(gè)數(shù)
int trailingZeroes(int n) {
    int a = 0;
    while(n>=5){
        n /= 5;
        a += n;
    }
    return a;
}

173. Binary Search Tree Iterator

  • 二叉樹的中序遍歷
  • 寫成外迭代器的形式
/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class BSTIterator {
    stack<TreeNode*> s;
public:
    BSTIterator(TreeNode *root) {
        auto p = root;
        while(p){
            s.push(p);
            p = p->left;
        }
    }

    /** @return whether we have a next smallest number */
    bool hasNext() {
        return !s.empty();
    }

    /** @return the next smallest number */
    int next() {
        auto p = s.top();
        s.pop();
        int val = p->val;
        p = p->right;
        while(p){
            s.push(p);
            p = p->left;
        }
        return val;
    }
};

/**
 * Your BSTIterator will be called like this:
 * BSTIterator i = BSTIterator(root);
 * while (i.hasNext()) cout << i.next();
 */

174. Dungeon Game

DP

  • 深搜,符合DP的兩個(gè)條件
  • 路徑上一直大于零著角。
class Solution {
public:
    int calculateMinimumHP(vector<vector<int>>& dungeon) {
        int m = dungeon.size();
        int n = dungeon[0].size();
        int d[n];
        d[n-1] = max(-dungeon[m-1][n-1], 0);
        for(int j=n-2;j>=0;j--)
            d[j] = max(d[j+1]-dungeon[m-1][j], 0);
        for(int i=m-2;i>=0;i--){
            d[n-1] = max(d[n-1]-dungeon[i][n-1], 0);
            for(int j=n-2;j>=0;j--){
                int cost = dungeon[i][j];
                d[j] = min(d[j]-cost, d[j+1]-cost);
                d[j] = max(d[j], 0);
            }
        }
        return d[0]+1;
    }
};

179. Largest Number

class Solution {
public:
    string largestNumber(vector<int>& nums) {
        vector<string> xs;
        for(int x: nums){
            stringstream ss;
            ss << x;
            xs.push_back(ss.str());
        }
        sort(begin(xs), end(xs),[](const string& a, const string& b){
            return a+b > b+a;
        });
        if(xs.size()==0 || xs[0]=="0")
            return "0";
        stringstream ss;
        for(auto& x: xs)
            ss << x;
        return ss.str();
    }
};

187. Repeated DNA Sequences

  • 查找
class Solution {
public:
    vector<string> findRepeatedDnaSequences(string s) {
        vector<string> result;
        unordered_map<char, int> m = {{'A',0},{'C',1},{'G',2},{'T',3}};
        unordered_map<int, int> h;
        int key = 0;
        for(int i=0; i<9; i++)
            key = (key<<2) | m[s[i]];
        for(int i=9; i<s.size(); i++){
            key = ((key<<2) | m[s[i]]) & ((1<<20) - 1);
            if(++h[key]==2)
                result.push_back(s.substr(i-9, 10));
        }
        return result;
    }
};

188. Best Time to Buy and Sell Stock IV

  • 買賣交替
  • k 很大的情況
  • k==2 的情況
class Solution {
public:
    int maxProfit(int k, vector<int>& prices) {
        if(k>=prices.size()/2){
            int ans = 0;
            for(int i=1; i<prices.size(); i++){
                int d = prices[i] - prices[i-1];
                ans += max(d, 0);
            }
            return ans;
        }        
        vector<int> l(k+1);
        vector<int> g(k+1);
        for(int i=1; i<prices.size();i++){
            int d = prices[i] - prices[i-1];
            for(int j=k; j>=1; j--){
                l[j] = max(g[j-1]+max(d,0), l[j]+d);
                g[j] = max(g[j], l[j]);
            }
        }
        return g[k];
    }
};

189. Rotate Array

Array

  • 數(shù)組問題
  • 三次逆置
void reverse(int* nums, int i, int j){
    for(; i<j; i++,j--){
        int t = nums[i];
        nums[i] = nums[j];
        nums[j] = t;
    }
}
void rotate(int* nums, int numsSize, int k) {
    k %= numsSize;
    if(k==0)
        return;
    reverse(nums,0,numsSize-k-1);
    reverse(nums,numsSize-k,numsSize-1);
    reverse(nums,0,numsSize-1);
}

190. Reverse Bits

uint32_t reverseBits(uint32_t n) {
    int a = 0;
    for(int i=0; i<32; i++){
        a <<= 1;
        a |= n&1;
        n >>= 1;
    }
    return a;
}

191. Number of 1 Bits

  • 整數(shù)位運(yùn)算經(jīng)典題
  • 一次迭代去掉一個(gè)最低位的1
    • 發(fā)生二進(jìn)制減法借位
int hammingWeight(uint32_t n) {
    int count = 0;
    while(n){
        count++;
        n &= n-1;
    }
    return count;
}

198. House Robber

DP

  • 應(yīng)用題揪漩,動(dòng)態(tài)規(guī)劃
class Solution {
public:
    int rob(vector<int>& nums) {
        int n = nums.size();
        if(n==0)
            return 0;
        if(n==1)
            return nums[0];
        vector<int> d(n);
        d[0] = nums[0];
        d[1] = max(d[0], nums[1]);
        for(int i=2; i<nums.size(); i++)
            d[i] = max(d[i-1], d[i-2]+nums[i]);
        return d[n-1];
    }
};

199. Binary Tree Right Side View

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> rightSideView(TreeNode* root) {
        vector<int> result;
        queue<TreeNode*> q;
        if(root)
            q.push(root);
        while(!q.empty()){
            result.push_back(q.back()->val);
            int n = q.size();
            while(n--){
                auto node = q.front();
                q.pop();
                if(node->left)
                    q.push(node->left);
                if(node->right)
                    q.push(node->right);
            }
        }
        return result;
    }
};

200. Number of Islands

Graph

void fill(char **grid, int m, int n, int y, int x) {
    if(grid[y][x]=='1'){
        grid[y][x] = '0';
        if(y>0)
            fill(grid, m, n, y-1, x);
        if(y+1<m)
            fill(grid, m, n, y+1, x);
        if(x>0)
            fill(grid, m, n, y, x-1);
        if(x+1<n)
            fill(grid, m, n, y, x+1);
    }
}
int numIslands(char** grid, int gridRowSize, int gridColSize) {
    int count = 0;
    for(int y=0;y<gridRowSize;y++)
        for(int x=0;x<gridColSize;x++){
            if(grid[y][x]=='1'){
                fill(grid, gridRowSize, gridColSize, y, x);
                count++;
            }
        }
    return count;
}

201. Bitwise AND of Numbers Range

Integer

  • 位運(yùn)算的轉(zhuǎn)化,覆蓋區(qū)間上的數(shù)
class Solution {
public:
    int rangeBitwiseAnd(int m, int n) {
        unsigned b = -1;
        while((m&b)!=(n&b))
            b <<= 1;
        return m&b;
    }
};

202. Happy Number

class Solution {
    int next(int x){
        int y = 0;
        while(x){
            y += (x%10)*(x%10);
            x /= 10;
        }
        return y;
    }
public:
    bool isHappy(int n) {
        unordered_map<int,bool> h;
        while(n!=1){
            if(h.count(n))
                return false;
            h[n] = true;
            n = next(n);
        }
        return true;
    }
};

203. Remove Linked List Elements

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        auto list = &head;
        while(*list){
            if((*list)->val==val)
                *list = (*list)->next;
            else
                list = &(*list)->next;
        }
        return head;
    }
};

204. Count Primes

  • 質(zhì)數(shù)
int countPrimes(int n) {
    int count = 0;
    bool h[n];
    memset(h,-1,sizeof(bool)*n);
    h[0] = h[1] = 0;
    for(int i=2; i<n; i++)
        if(h[i])
            for(int j=i<<1; j<n; j+=i)
                h[j] = 0;
    for(int i=0; i<n; i++)
        if(h[i])
            count++;
    return count;
}

205. Isomorphic Strings

bool isIsomorphic(char* s, char* t) {
    char h[128] = {0}, r[128] = {0};
    while(*s){
        if(h[*s] == 0 && r[*t]==0){
            h[*s] = *t;
            r[*t] = *s;
        }else if(h[*s]!=*t)
            return false;
        s++, t++;
    }
    return true;
}

206. Reverse Linked List

  • 鏈表經(jīng)典問題
  • 原地逆置鏈表
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* prev = NULL;
        while(head){
            ListNode* next = head->next;
            head->next = prev;
            prev = head;
            head = next;
        }
        return prev;
    }
};

207. Course Schedule

Graph

  • 有趣的題目
  • 有向圖拓?fù)渑判蚶艨冢袛嗍欠裼协h(huán)
    • 用深度優(yōu)先搜索實(shí)現(xiàn)
class Solution {
public:
    bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
        unordered_map<int,int> h;
        function<bool(int)> f = [&](int x){
            if(h[x]==1)
                return true;
            if(h[x]==2)
                return false;
            h[x] = 1;
            for(auto p: prerequisites)
                if(p.first==x){
                    if(f(p.second))
                        return true;
                }
            h[x] = 2;
            return false;
        };
        for(int i=0; i<numCourses; i++)
            if(f(i))
                return false;
        return true;
    }
};

208. Implement Trie (Prefix Tree)

  • 字符串查找奄容,前綴
  • 后面有個(gè)題目會(huì)用到這個(gè)數(shù)據(jù)結(jié)構(gòu)
class Trie {
    struct Node{
        Node* next[26];
        bool term;
        Node(){
            memset(this,0,sizeof(Node));
        }
    };
    Node* root;
public:
    /** Initialize your data structure here. */
    Trie() {
        root = new Node();
    }
    
    /** Inserts a word into the trie. */
    void insert(string word) {
        Node* node = root;
        for(char c: word){
            Node*& next = node->next[c-'a'];
            if(!next)
                next = new Node();
            node = next;
        }
        node->term = true;
    }
    
    /** Returns if the word is in the trie. */
    bool search(string word) {
        Node* node = root;
        for(char c: word){
            node = node->next[c-'a'];
            if(!node)
                return false;            
        }
        return node->term;
    }
    
    /** Returns if there is any word in the trie that starts with the given prefix. */
    bool startsWith(string prefix) {
        Node* node = root;
        for(char c: prefix){
            node = node->next[c-'a'];
            if(!node)
                return false;
        }
        return true;
    }
};

/**
 * Your Trie object will be instantiated and called as such:
 * Trie obj = new Trie();
 * obj.insert(word);
 * bool param_2 = obj.search(word);
 * bool param_3 = obj.startsWith(prefix);
 */

209. Minimum Size Subarray Sum

Array

  • 雙指針
class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) {
        int len = nums.size()+1;
        int sum = 0;
        int j = 0;
        for(int i=0; i<nums.size(); i++){
            sum += nums[i];
            while(j<i && sum-nums[j]>=s){
                sum -= nums[j];
                j++;
            }
            if(sum>=s)
                len = min(len, i-j+1);
            printf("%d->%d: %d %d\n",j,i,sum,len);
        }
        return len==nums.size()+1 ? 0 : len;
    }
};

210. Course Schedule II

  • 有其他實(shí)現(xiàn)方式
class Solution {
public:
    vector<int> findOrder(int numCourses, vector<pair<int, int>>& prerequisites) {
        vector<int> ans;
        unordered_map<int,int> h;
        function<bool(int)> f = [&](int x){
            if(h[x]==1)
                return true;
            if(h[x]==2)
                return false;
            h[x] = 1;
            for(auto p: prerequisites)
                if(p.first==x){
                    if(f(p.second))
                        return true;
                }
            h[x] = 2;
            ans.push_back(x);
            return false;
        };
        for(int i=0; i<numCourses; i++)
            if(f(i))
                return {};
        return ans;
    }
};

211. Add and Search Word - Data structure design

  • Trie (Prefix Tree)
  • DFS
class WordDictionary {
    struct TrieNode{
        TrieNode* next[26];
        bool term;
        TrieNode(){
            memset(this,0,sizeof(TrieNode));
        }
    };
    TrieNode* root;
public:
    /** Initialize your data structure here. */
    WordDictionary() {
        root = new TrieNode();
    }
    
    /** Adds a word into the data structure. */
    void addWord(string word) {
        auto node = root;
        for(char c: word){
            auto& next = node->next[c-'a'];
            if(!next)
                next = new TrieNode();
            node = next;
        }
        node->term = true;        
    }
    
    /** Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. */
    bool search(string word) {
        return _search(word.c_str(), root);
    }
    bool _search(const char* s, TrieNode* root){
        for(;;)
            if(*s==0){
                return root->term;
            }else if(*s=='.'){
                for(int i=0; i<26; i++){
                    if(root->next[i] && _search(s+1, root->next[i]))
                        return true;
                }
                return false;
            }else{
                root = root->next[*s-'a'];
                s++;
                if(root==NULL)
                    return false;
            }
    }
};

/**
 * Your WordDictionary object will be instantiated and called as such:
 * WordDictionary obj = new WordDictionary();
 * obj.addWord(word);
 * bool param_2 = obj.search(word);
 */

212. Word Search II

class Solution {
    struct TrieNode{
        TrieNode* next[26];
        const char* term;
        TrieNode(){
            memset(this,0,sizeof(TrieNode));
        }
    };
    TrieNode* root = new TrieNode();
    void insert(string& word) {
        auto node = root;
        for(char c: word){
            auto& next = node->next[c-'a'];
            if(!next)
                next = new TrieNode();
            node = next;
        }
        node->term = word.c_str();
        printf("> %s\n",node->term);
    }
public:
    vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
        for(auto& word: words){
            insert(word);
        }
        int m = board.size();
        int n = board[0].size();
        vector<string> ans;
        function<void(int,int,TrieNode*)> f = [&](int y, int x, TrieNode* node){
            char c = board[y][x];
            if(c==0)
                return;
            auto next = node->next[c-'a'];
            if(next==NULL)
                return;
            if(next->term){
                ans.push_back(next->term);
                next->term = NULL;
            }                
            board[y][x] = 0;
            if(x>0)
                f(y, x-1, next);
            if(x+1<n)
                f(y, x+1, next);
            if(y>0)
                f(y-1, x, next);
            if(y+1<m)
                f(y+1, x, next);
            board[y][x] = c;
        };
        for(int y=0;y<m;y++){
            for(int x=0;x<n;x++){
                f(y, x, root);
            }
        }
        return ans;
    }
};

213. House Robber II

DP

class Solution {
    int rob1(vector<int>& nums, int s, int n) {
        if(n==1)
            return nums[s];
        vector<int> d(n);
        d[0] = nums[s];
        d[1] = max(d[0], nums[s+1]);
        for(int i=2; i<n; i++)
            d[i] = max(d[i-1], d[i-2]+nums[s+i]);
        return d[n-1];
    }    
public:
    int rob(vector<int>& nums) {
        int n = nums.size();
        if(n==0)
            return 0;
        if(n==1)
            return nums[0];
        return max(rob1(nums,0,n-1),rob1(nums,1,n-1));
    }
};
class Solution {
    int rob1(vector<int>& nums, int s, int n) {
        if(n==1)
            return nums[s];
        int a = 0, b = 0;
        for(int i=0; i<n; i++){
            int c = max(b, a+nums[s+i]);
            a = b;
            b = c;
        }
        return b;
    }    
public:
    int rob(vector<int>& nums) {
        int n = nums.size();
        if(n==0)
            return 0;
        if(n==1)
            return nums[0];
        return max(rob1(nums,0,n-1),rob1(nums,1,n-1));
    }
};

214. Shortest Palindrome

class Solution {
public:
    string shortestPalindrome(string s) {
        auto s2 = s;
        reverse(s2.begin(),s2.end());
        string m = s + "#" + s2;
        int n = m.size();
        int b[n+1];
        int i = 0, j = -1;
        b[i] = j;
        while(i<n){
            while(j>=0 && m[i]!=m[j])
                j = b[j];
            i++, j++;
            b[i] = j;
        }
        return s2.substr(0, s.size()-b[n]) + s;
    }
};

215. Kth Largest Element in an Array

Sort

  • 題目是查找闸翅,用排序
  • quicksort
  • heap
class Solution {
    int partition(vector<int>& A, int a, int b){
        int pivot = A[b];
        int i = a;
        for(int j=a;j<b;j++)
            if(A[j]<pivot){
                swap(A[i], A[j]);
                i++;
            }
        swap(A[i], A[b]);
        return i;
    }
    int search(vector<int>& nums, int a, int b, int k){
        if(a<=b){
            int p = partition(nums, a, b);
            int rest = b - p;
            if(k-1==rest)
                return nums[p];
            else if(k<=rest)
                return search(nums, p+1, b, k);    
            else
                return search(nums, a, p-1, k-rest-1);
        }
        return -1;
    }
public:
    int findKthLargest(vector<int>& nums, int k) {
        return search(nums, 0, nums.size()-1, k);
    }
};
class Solution {
    int partition(vector<int>& A, int a, int b){
        int pivot = A[b];
        int i = a;
        for(int j=a;j<b;j++)
            if(A[j]<pivot){
                swap(A[i], A[j]);
                i++;
            }
        swap(A[i], A[b]);
        return i;
    }
    int search(vector<int>& nums, int a, int b, int k){
        while(a<=b){
            int p = partition(nums, a, b);
            int rest = b - p;
            if(k-1==rest){
                return nums[p];
            }else if(k<=rest){
                a = p+1;
            }else{
                b = p-1;
                k = k-rest-1;
            }
        }
        return -1;
    }
public:
    int findKthLargest(vector<int>& nums, int k) {
        return search(nums, 0, nums.size()-1, k);
    }
};

216. Combination Sum III

  • 拿前面有道題題小改一下就行
class Solution {
public:
    vector<vector<int>> combinationSum3(int k, int n) {
        vector<vector<int>> result;
        int sum = 0;
        vector<int> item;
        function<void(int)> loop = [&](int i){
            if(sum==n && item.size()==k){
                result.push_back(item);
                return;
            }
            if(sum>n || item.size()==k)
                return;
            for(int j=i;j<=9;j++){
                sum += j;
                item.push_back(j);
                loop(j+1);
                sum -= j;
                item.pop_back();
            }
        };
        loop(1);
        return result;        
    }
};

217. Contains Duplicate

  • 這題沒意思,是前面的題目的簡(jiǎn)化版本
class Solution {
public:
    bool containsDuplicate(vector<int>& nums) {
        unordered_map<int,bool> h;
        for(int x: nums){
            if(h[x])
                return true;
            h[x] = true;
        }
        return false;
    }
};

218. The Skyline Problem

  • 排序拐點(diǎn)
  • 橫坐標(biāo)相同的點(diǎn)先插后刪除
class Solution {
public:
    vector<pair<int, int>> getSkyline(vector<vector<int>>& buildings) {
         vector<pair<int, int>> ans;
         vector<pair<int, int>> w;
         for(auto& x: buildings){
             w.push_back({x[0],-x[2]});
             w.push_back({x[1],x[2]});
         }
         sort(w.begin(),w.end());
         multiset<int> tree = {0};
         int prev = 0;
         for(auto& x: w){
             if(x.second<0)
                 tree.insert(-x.second);
             else
                 tree.erase(tree.find(x.second));
             int top = *tree.rbegin();
             if(top!=prev){
                ans.push_back({x.first, top});
                prev = top;
             };
         }
         return ans;
    }
};

219. Contains Duplicate II

class Solution {
public:
    bool containsNearbyDuplicate(vector<int>& nums, int k) {
        unordered_map<int,int> h;
        for(int i=0; i<nums.size(); i++){
            auto it = h.find(nums[i]);
            if(it!=h.end() && i-it->second<=k)
                return true;
            h[nums[i]] = i;
        }
        return false;
    }
};

220. Contains Duplicate III

  • 滑動(dòng)窗口
  • 用搜索樹戈盈,或者哈希表
class Solution {
public:
    bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
        multiset<long long> tree;
        for(int i=0; i<nums.size(); i++){
            long x = nums[i];
            if(i-k-1>=0)
                tree.erase(tree.lower_bound(nums[i-k-1]));
            auto it = tree.lower_bound(x-t);
            if(it!=tree.end() && distance(it, tree.upper_bound(x+t))>0)
                return true;

            tree.insert(nums[i]);
        }
        return false;
    }
};
  • lower_bound 返回大于等于的元素
class Solution {
public:
    bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
        multiset<long long> tree;
        for(int i=0; i<nums.size(); i++){
            long x = nums[i];
            if(i-k-1>=0)
                tree.erase(tree.lower_bound(nums[i-k-1]));
            auto it = tree.lower_bound(x-t);
            if(it!=tree.end() && *it<=x+t)
                return true;
            tree.insert(nums[i]);
        }
        return false;
    }
};

221. Maximal Square

  • 挺標(biāo)準(zhǔn)的動(dòng)態(tài)規(guī)劃的題目
    • 非常標(biāo)準(zhǔn)
    • 畫圖推演一下
class Solution {
public:
    int maximalSquare(vector<vector<char>>& matrix) {
        int m = matrix.size();
        if(m==0)
            return 0;
        int n = matrix[0].size();
        int ans = 0;
        vector<int> d(n, 0);
        for(int x=0;x<n;x++)
            if(matrix[0][x]-'0')
                ans = d[x] = 1;
        for(int y=1;y<m;y++){
            int c = d[0];
            d[0] = matrix[y][0]-'0';
            ans = max(ans, d[0]);
            for(int x=1;x<n;x++){
                int t = d[x];
                if(matrix[y][x]-'0'){
                    d[x] = min(c, min(d[x], d[x-1]))+1;
                    ans = max(ans, d[x]);
                }else{
                    d[x] = 0;
                }
                c = t;
            }
        }
        return ans*ans;
    }
};

222. Count Complete Tree Nodes

  • 很容易超時(shí)
  • 利用題目中完全二叉樹的性質(zhì)做優(yōu)化
  • 滿二叉樹有 2^k-1 個(gè)節(jié)點(diǎn)
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int countNodes(TreeNode* root) {
        int d1 = 0, d2 = 0;
        for(auto p=root; p; p=p->left)
            d1++;
        for(auto p=root; p; p=p->right)
            d2++;
        if(d1==d2)
            return pow(2, d1)-1;
        else
            return countNodes(root->left)+countNodes(root->right)+1;        
    }
};

223. Rectangle Area

  • 計(jì)算兩個(gè)矩形的總面積
  • 可能有重疊部分
class Solution {
public:
    int computeArea(int A, int B, int C, int D, int E, int F, int G, int H) {
        int I = max(A,E), J = max(B,F), K= min(C,G), L=min(D,H);
        return (C-A)*(D-B)+(G-E)*(H-F)-( K>I && L>J ?(K-I)*(L-J) : 0);
    }
};

224. Basic Calculator

class Solution {
    int priority(char c){
        switch(c){
            case '+':
            case '-':
                return 1;
            case '*':
            case '/':
                return 2;
            default:
                return 0;
        }
    }
    void operate(){
        int y = nums.top();
        nums.pop();
        int x = nums.top();
        nums.pop();
        switch(ops.top()){
            case '+':
                nums.push(x+y);
                break;
            case '-':
                nums.push(x-y);
                break;
            case '*':
                nums.push(x*y);
                break;            
            case '/':
                nums.push(x/y);
                break;
        }
        ops.pop();
    }
    stack<int> nums;
    stack<char> ops;    
public:
    int calculate(string s) {
        char c;
        const char *p = s.c_str();
        while((c=*p)){
            printf("> %c\n",c);
            switch(c){
                case ' ':
                    p++;
                    break;
                case '+':
                case '-':
                case '*':
                case '/':
                    while(!ops.empty() && priority(c)<=priority(ops.top()))
                        operate();
                    ops.push(c);
                    p++;
                    break; 
                case '(':
                    ops.push(c);
                    p++;
                    break;
                case ')':
                    while(ops.top()!='(')
                        operate();
                    ops.pop();
                    p++;
                    break;
                default:
                    char *e;
                    int x = strtol(p, &e, 10);
                    nums.push(x);
                    p = e;
            }
        }
        while(!ops.empty())
            operate();
        return nums.top();
    }
};
  • 沒有乘除法痊夭,只有加減和正整數(shù)刁岸,可以簡(jiǎn)化
  • 求和,帶符號(hào)
class Solution {
public:
    int calculate(string s) {
        int ans = 0;
        stack<int> signs;
        signs.push(1);
        int sign = 1;
        const char *p = s.c_str();
        char c;        
        for(;;){
            switch(*p){
                case 0:
                    goto end_for;
                case ' ':
                    p++;
                    break;
                case '+':
                    sign = 1;
                    p++;
                    break;
                case '-':
                    sign = -1;
                    p++;
                    break; 
                case '(':
                    signs.push(sign*signs.top());
                    sign = 1;
                    p++;
                    break;
                case ')':
                    signs.pop();
                    sign = 1;
                    p++;
                    break;
                default:
                    char *e;
                    int x = strtol(p, &e, 10);
                    ans += signs.top()*sign*x;
                    p = e;
            }
        }
        end_for:
        return ans;
    }
};

225. Implement Stack using Queues

  • 可以用 size(queue)
  • 出入有一個(gè)操作為 O(N)
  • 可以不需要額外空間
class MyStack {
    queue<int> q1, q2;
public:
    /** Initialize your data structure here. */
    MyStack() {
        
    }
    
    /** Push element x onto stack. */
    void push(int x) {
        q2.push(x);
    }
    
    /** Removes the element on top of the stack and returns that element. */
    int pop() {
        while(q2.size()>1){
            q1.push(q2.front());
            q2.pop();
        }
        int y = q2.front();
        q2.pop();
        q1.swap(q2);
        return y;
    }
    
    /** Get the top element. */
    int top() {
        int y = pop();
        q2.push(y);
        return y;
    }
    
    /** Returns whether the stack is empty. */
    bool empty() {
        return q2.empty();
    }
};

/**
 * Your MyStack object will be instantiated and called as such:
 * MyStack obj = new MyStack();
 * obj.push(x);
 * int param_2 = obj.pop();
 * int param_3 = obj.top();
 * bool param_4 = obj.empty();
 */

226. Invert Binary Tree

  • 二叉樹遍歷
class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if(root==nullptr)
            return nullptr;
        swap(root->left, root->right);
        invertTree(root->left);
        invertTree(root->right);
        return root;
    }
};

227. Basic Calculator II

  • 前面那題的特例/子集
  • 不叫優(yōu)化她我,叫簡(jiǎn)化/特殊化
int calculate(char* s) {
    int ans = 0;
    int x = strtol(s,&s,10);
    while(*s){
        while(isspace(*s))
            s++;
        char op = *s++;
        int y = strtol(s,&s,10);
        switch(op){
            case '+':
                ans += x;
                x = y;
                break;
            case '-':
                ans += x;
                x = -y;
                break;
            case '*':
                x *= y;
                break;
            case '/':
                x /= y;
                break;
        }
    }
    ans += x;
    return ans;
}
class Solution {
public:
    int calculate(string s) {
        stack<int> st;
        int x;
        const char *p = s.c_str();
        st.push(strtol(p,(char**)&p,10));
        while(*p){
            while(isspace(*p))
                p++;
            char op = *p++;
            int x, y = strtol(p,(char**)&p,10);
            switch(op){
                case '+':
                    st.push(y);
                    break;
                case '-':
                    st.push(-y);
                    break;
                case '*':
                    x = st.top();
                    st.pop();
                    st.push(x*y);
                    break;
                case '/':
                    x = st.top();
                    st.pop();
                    st.push(x/y);                
                    break;
            }
        }
        int ans = 0;
        while(!st.empty()){
            ans += st.top();
            st.pop();
        }
        return ans;
    }
};

228. Summary Ranges

class Solution {
public:
    vector<string> summaryRanges(vector<int>& nums) {
        vector<string> ans;
        stringstream b;
        int s = 0;
        for(int i=1; s!=nums.size(); i++){
            if(i==nums.size() || nums[i]!=nums[i-1]+1){
                if(s==i-1){
                    ans.push_back(to_string(nums[i-1]));
                }else{
                    stringstream b;
                    b << nums[s] << "->" << nums[i-1];
                    ans.push_back(b.str());
                }
                s = i;
            }
        }
        return ans;
    }
};

229. Majority Element II

class Solution {
public:
    vector<int> majorityElement(vector<int>& nums) {
        int a = 0, ca = 0;
        int b = 0, cb = 0;
        for(int x: nums){
            if(x==a){
                ca++;
            }else if(x==b){
                cb++;
            }else if(ca==0){
                a = x, ca = 1;
            }else if(cb==0){
                b = x, cb = 1;
            }else{
                cb--, ca--;
            }
        }
        ca = cb = 0;
        for(int x: nums){
            if(x==a)
                ca++;
            else if(x==b)
                cb++;
        }
        vector<int> ans;
        if(ca>nums.size()/3)
            ans.push_back(a);
        if(cb>nums.size()/3)
            ans.push_back(b);
        return ans;
    }
};

230. Kth Smallest Element in a BST

Tree

  • 這題本身沒什么虹曙,附加問挺有意思的
  • 依然基于排序二叉樹的模版迫横,針對(duì)題目做適當(dāng)?shù)膬?yōu)化
    • 在二叉樹添加和查找的時(shí)候,在每個(gè)節(jié)點(diǎn)維持做節(jié)點(diǎn)個(gè)數(shù)酝碳。
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
    int count = 0;
    int ans;
    bool f(TreeNode* root){
        if(!root)
            return false;
        if(f(root->left))
            return true;
        count--;
        if(count==0){
            ans = root->val;
            return true;
        }
        if(f(root->right))
            return true;
        return false;
    }
public:
    int kthSmallest(TreeNode* root, int k) {
        count = k;
        f(root);
        return ans;
    }
};

231. Power of Two

  • 是 2, 4, 8, 16, 32, 64 ...
  • 利用二進(jìn)制中 1 的個(gè)數(shù)的那題矾踱,判斷最高位
class Solution {
public:
    bool isPowerOfTwo(int n) {
        return n>0 && !(n&(n-1));
    }
};

232. Implement Queue using Stacks

Stack

  • 在函數(shù)式不可變的數(shù)據(jù)結(jié)構(gòu)中用得到
class Queue {
    stack<int> s1;
    stack<int> s2;
    void enq(){
        while(!s2.empty()){
            s1.push(s2.top());
            s2.pop();
        }
    }
public:
    // Push element x to the back of queue.
    void push(int x) {
        s2.push(x);
    }

    // Removes the element from in front of queue.
    void pop(void) {
        if(s1.empty())
            enq();
        s1.pop();
    }

    // Get the front element.
    int peek(void) {
        if(s1.empty())
            enq();
        return s1.top();
    }

    // Return whether the queue is empty.
    bool empty(void) {
        return s1.empty() && s2.empty();
    }
};

233. Number of Digit One

Integer

class Solution {
public:
    int countDigitOne(int n) {
        int a=0, b=1, c=1;
        while(n){
            a += (n + 8) / 10 * b; 
            if(n%10==1)
                a += c;
            c += (n%10)*b;
            b *= 10;
            n /= 10;
        }
        return a;
    }
};

234. Palindrome Linked List

  • 拿前面有道鏈表題改改就行
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
    ListNode* cut(ListNode* head){
        if(!head)
            return NULL;
        auto slow = head, fast = head;
        while(fast && fast->next && fast->next->next){
            slow = slow->next;
            fast = fast->next->next;
        }
        auto head2 = slow->next;
        slow->next;
        return head2;
    }
    ListNode* reverse(ListNode* head){
        ListNode* prev = NULL;
        while(head){
            auto next = head->next;
            head->next = prev;
            prev = head;
            head = next;
        }
        return prev;        
    }
public:
    bool isPalindrome(ListNode* head) {
        auto head2 = reverse(cut(head));
        for(auto p=head,q=head2; p&&q; p=p->next,q=q->next)
            if(p->val!=q->val)
                return false;
        return true;
    }
};

235. Lowest Common Ancestor of a Binary Search Tree

  • 已知根節(jié)點(diǎn)
  • 利用二叉排序樹的節(jié)點(diǎn)值的關(guān)系
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        for(;;)
            if(root->val > p->val && root->val > q->val){
                root = root->left;
            }else if(root->val < p->val && root->val < q->val){
                root = root->right;
            }else{
                return root;
            }
    }
};

236. Lowest Common Ancestor of a Binary Tree

  • 遞歸,驗(yàn)證左右節(jié)點(diǎn)是否為父節(jié)點(diǎn)
    • 都不是疏哗,則自己是
    • 有一個(gè)是呛讲,在那邊
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(!root || root==p || root==q)
            return root;
        auto left = lowestCommonAncestor(root->left, p, q);
        auto right = lowestCommonAncestor(root->right, p, q);
        if(left && right)
            return root;
        return left ? left : right;
    }
};

237. Delete Node in a Linked List

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    void deleteNode(ListNode* node) {
        auto next = node->next;
        assert(next);
        *node = *next;
        delete next;
    }
};

238. Product of Array Except Self

  • 題目要求不用除法,那就左右來回兩趟
    • 左邊乘以右邊
class Solution {
public:
    vector<int> productExceptSelf(vector<int>& nums) {
        int n = nums.size();
        vector<int> ans(n);
        int c = 1;
        for(int i=0; i<n; i++){
            ans[i] = c;
            c *= nums[i];
        }
        c = 1;
        for(int i=n-1; i>=0; i--){
            ans[i] *= c;
            c *= nums[i];
        }
        return ans;
    }
};

239. Sliding Window Maximum

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        if(nums.size()<k || k==0)
            return {};
        vector<int> m;
        deque<int> q;
        for(int i=0; i<k; i++){
            while(!q.empty() && nums[i]>=nums[q.back()])
                q.pop_back();
            q.push_back(i);
        }
        for(int i=k; i<nums.size(); i++){
            m.push_back(nums[q.front()]);
            while(!q.empty() && nums[i]>=nums[q.back()])
                q.pop_back();
            while(!q.empty() && q.front()<=i-k)
                q.pop_front();
            q.push_back(i);
        }
        m.push_back(nums[q.front()]);
        return m;
    }
};

240. Search a 2D Matrix II

  • 從右上角/左下角開始搜索圣蝎,往左下/右上方向進(jìn)行
class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        int m = matrix.size();
        if(m==0)
            return false;
        int n = matrix[0].size();
        int x = n-1, y=0;
        while(y<m && x>=0){
            if(matrix[y][x]==target){
                return true;
            }if(matrix[y][x]<target)
                y++;
            else{
                x--;
            }
        }
        return false;
    }
};

241. Different Ways to Add Parentheses

Search

  • 表達(dá)式語法樹,這里是二叉樹
    • 每個(gè)符號(hào)都有機(jī)會(huì)做根節(jié)點(diǎn)
  • 不要遺漏解衡瓶,挺容易遺漏的
  • 求全部解,笛卡爾積
    • 遞歸函數(shù)返回?cái)?shù)組牲证,或者使用回調(diào)
    • 存在左右子樹兩個(gè)方向哮针,都各有若干可能
      • 這是這道題有趣的地方
class Solution {
    const char* s;
    void f(int a, int b, function<void(int)> c){
        bool flag = false;
        for(int i=a; i<=b; i++){
            switch(s[i]){
                case '+':
                    flag = true;
                    f(a,i-1,[&](int x){
                        f(i+1,b,[&](int y){
                            c(x+y);
                        });
                    });
                    break;
                case '-':
                    flag = true;
                    f(a,i-1,[&](int x){
                        f(i+1,b,[&](int y){
                            c(x-y);
                        });
                    });                
                    break;
                case '*':
                    flag = true;
                    f(a,i-1,[&](int x){
                        f(i+1,b,[&](int y){
                            c(x*y);
                        });
                    });                
                    break;
            }
        }
        if(!flag){
            c(strtol(s+a,0,10));
        }
    }
public:
    vector<int> diffWaysToCompute(string input) {
        vector<int> ans;
        this->s = input.c_str();
        f(0,input.size()-1,[&](int z){
            ans.push_back(z);
        });
        return ans;
    }
};

242. Valid Anagram

  • 排序,或者哈希
class Solution {
public:
    bool isAnagram(string s, string t) {
        sort(s.begin(), s.end());
        sort(t.begin(), t.end());
        return s==t;
    }
};
class Solution {
public:
    bool isAnagram(string s, string t) {
        unordered_map<char,int> h;
        for(char x: s)
            h[x]++;
        for(char x: t)
            h[x]--;
        for(auto p: h)
            if(p.second)
                return false;
        return true;
    }
};

索引

歸類

解答 1.5

有鎖的題放這里

解答 2

以下用來嘗試一些不那么好的解法坦袍。

有的是不符合題目的全部要求十厢,有的就是隨手寫寫的。

部分題目的解答

用 Ruby

擴(kuò)展想法用捂齐,寫一些并不一定完全復(fù)合題目要求蛮放。

注意

  • Ruby 負(fù)數(shù)除法的取整方向和 C 不一樣

1. Two Sum

  • array + hash
def two_sum(nums, target)
  h = {}
  for x, i in nums.each_with_index
    return h[x], i if h.key? x
    h[target-x] = i
  end
end

2. Add Two Numbers

def add_two_numbers(l1, l2)
    list = node = ListNode.new(nil)
    c = 0
    while l1 || l2 || c!=0
        if l1
            c += l1.val
            l1 = l1.next
        end
        if l2
            c += l2.val
            l2 = l2.next
        end
        node.next = ListNode.new(c%10)
        c /= 10
        node = node.next
    end
    list.next
end

3. Longest Substring Without Repeating Characters

# @param {String} s
# @return {Integer}
def length_of_longest_substring(s)
  ans = 0
  h = Hash.new(-1)
  j = -1
  for c, i in s.each_char.with_index
    j = [j, h[c]].max
    h[c] = i
    ans = [ans, i-j].max
  end
  ans
end

17. Letter Combinations of a Phone Number

  • 回溯
  • 這題每一步不需要加條件,后面的回溯題會(huì)先過濾路徑上的點(diǎn)奠宜。
  • 回溯的每一項(xiàng)是“或”的關(guān)系
# @param {String} digits
# @return {String[]}
def letter_combinations(digits)
    h = ["","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"]
    f = ->(s){
        if s.empty?
            [""]
        else
            h[s[0].to_i].chars.flat_map{|x|
                f.(s[1..-1]).map{|y|
                    x+y
                }
            }
        end
    }
    digits.empty? ? [] : f.(digits)
end
# @param {String} digits
# @return {String[]}
def letter_combinations(digits)
    h = ["","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"]
    f = ->(i){
        if i==digits.size
            [""]
        else
            h[digits[i].to_i].chars.flat_map{|x|
                f.(i+1).map{|y|
                    x+y
                }
            }
        end
    }
    digits.empty? ? [] : f.(0)
end

上面這個(gè)以后刪掉

# @param {String} digits
# @return {String[]}
def letter_combinations(digits)
    return [] if digits.empty?
    h = ["","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"]
    ans = []
    path = []
    f = ->(i){
        if i==digits.size
            ans.push path*''
        else
            for c in h[digits[i].to_i].chars
                path.push c
                f.(i+1)
                path.pop
            end
        end
    }
    f.(0)
    ans
end

寫成用 Stack 的形式

# @param {String} digits
# @return {String[]}
def letter_combinations(digits)
    h = ["","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"]
    ans = []
    stack = []
    stack.push(-1)
    while !stack.empty?
        stack[-1] += 1
        p stack
        if stack[-1]>=h[digits[stack.size-1].to_i].size
            stack.pop
        elsif stack.size==digits.size
            ans.push stack.map.with_index{|x,i|
                h[digits[i].to_i][x]
            }*''
        else
            stack.push(-1)
        end
    end
    ans
end
def letter_combinations(digits)
    h = ["","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"]
    return [] if digits.empty?
    ans = []
    stack = []
    stack.push(-1)
    path = []
    while x = stack.pop
        if stack.size==digits.size
            ans.push path*''
            path.pop
            next
        end
        x += 1
        if x>=h[digits[stack.size].to_i].size
            path.pop
        else
            path.push(h[digits[path.size].to_i][x])
            stack.push(x)
            stack.push(-1)
        end
    end
    ans
end
def letter_combinations(digits)
    h = ["","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"]
    return [] if digits.empty?
    ans = []
    stack = []
    stack.push(-1)
    path = []
    while !stack.empty?
        if stack.size>digits.size
            ans.push path*''
            path.pop
            stack.pop
            next
        end
        stack[-1] += 1
        if stack[-1]>=h[digits[stack.size-1].to_i].size
            path.pop
            stack.pop
        else
            path.push(h[digits[path.size].to_i][stack[-1]])
            stack.push(-1)
        end
    end
    ans
end
def letter_combinations(digits)
    h = ["","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"]
    return [] if digits.empty?
    ans = []
    stack = []
    stack.push(-1)
    path = []
    while !stack.empty?
        if stack.size>digits.size
            ans.push path*''
            stack.pop
            next
        end
        o = stack[-1]
        stack[-1] += 1
        if stack[-1]>=h[digits[stack.size-1].to_i].size
            path.pop if o!=-1
            stack.pop
        else
            path.pop if o!=-1
            path.push(h[digits[path.size].to_i][stack[-1]])
            stack.push(-1)
        end
    end
    ans
end

38. Count and Say

def count_and_say(n)
    (n-1).times.inject("1"){|a,b|a.chars.chunk(&:itself).map{|k,v|"#{v.size}#{k}"}*''}
end

49. Group Anagrams

def group_anagrams(strs)
    strs.group_by{|x|x.chars.sort}.values
end

51. N-Queens

def solve_n_queens(n)
  a = [nil]*n
  b = [false]*n
  c = [false]*(2*n-1)
  d = [false]*(2*n-1)
  ys = []
  f = ->(i){
    if i < n
      for j in 0...n
        unless b[j] || c[i+j] || d[i-j+n-1]
          a[i] = j
          b[j] = c[i+j] = d[i-j+n-1] = true
          f.(i + 1)
          b[j] = c[i+j] = d[i-j+n-1] = false
        end
      end
    else
      ys << a.collect{|x|
          line = "."*n
          line[x] = ?Q
          line
      }
    end
  }
  f[0]
  ys
end

65. Valid Number

def is_number(s)
    s=~/^\s*[-+]?(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?\s*$/ ? true : false;
end

66. Plus One

def plus_one(digits)
    (digits.size-1).downto(0) do |i|
        if(digits[i]!=9)
            digits[i] += 1
            return digits
        end
        digits[i] = 0
    end
    digits.unshift(1)
    return digits
end

78. Subsets

def subsets(nums)
    (1<<nums.length).times.map{|i|nums.select.with_index{|x,j|(i>>j)&1==1}}
end

94. Binary Tree Inorder Traversal

def inorder_traversal(root)
    result = []
    stack = []
    node = root
    while node || !stack.empty?
        if node
            stack << node
            node = node.left
        else
            node = stack.pop
            result << node.val
            node = node.right
        end
    end
    result
end
def inorder_traversal(root)
    result = []
    stack = []
    node = root
    while true
        if node
            stack << node
            node = node.left
        elsif !stack.empty?
            node = stack.pop
            result << node.val
            node = node.right
        else
            break
        end
    end
    result
end

102. Binary Tree Level Order Traversal

  • 二叉樹層次遍歷
def level_order(root)
    result = []
    queue = []
    queue << root if root
    until queue.empty?
        result << queue.map(&:val)
        queue.size.times do
            node = queue.shift
            queue << node.left if node.left
            queue << node.right if node.right
        end
    end
    result
end

144. Binary Tree Preorder Traversal

def preorder_traversal(root)
    result = []
    stack = []
    stack << root if root
    while node = stack.pop
        result << node.val
        stack << node.right if node.right
        stack << node.left if node.left
    end
    result
end

145. Binary Tree Postorder Traversal

def postorder_traversal(root)
    result = []
    stack = []
    node = root
    prev = nil
    while true
        if node
            stack << node
            node = node.left
        elsif !stack.empty?
            node = stack.last
            if prev==node.right || node.right.nil?
                result << node.val
                prev, node = node, nil
                stack.pop
            else
                node = node.right
            end
        else
            break
        end
    end
    result
end

208. Implement Trie (Prefix Tree)

class Trie

    def initialize()
        @root = {}
    end

    def insert(word)
        node = @root
        word.each_char do |c|
            node = node[c]||={}
        end
        node[nil] = true        
    end

    def search(word)
        node = @root
        word.each_char do |c|
            node = node[c] or return false
        end
        node[nil]==true
    end

    def starts_with(prefix)
        node = @root
        prefix.each_char do |c|
            node = node[c] or return false
        end
        true
    end

end

217. Contains Duplicate

def contains_duplicate(nums)
    h = {}
    nums.each do |e|
        return true if h[e]
        h[e] = true
    end
    false
end
def contains_duplicate(nums)
    nums.sort!
    for i in 1...nums.size
        return true if nums[i]==nums[i-1]
    end
    false
end

224. Basic Calculator

def calculate(s)
    ans = 0
    stack = [1]
    sign = 1
    s.scan(/\d+|[+\-()]/) do |x|
        case x
        when ?+
            sign = stack.last
        when ?-
            sign = -stack.last
        when ?(
            stack << sign
            sign = stack.last
        when ?)
            stack.pop
        else
            ans += sign*x.to_i
        end
    end
    ans
end

227. Basic Calculator II

def calculate(s)
    ans = 0
    e = s.scan(/\d+|[+\-*\/]/)
    x = e.shift.to_i
    while op = e.shift
        y = e.shift.to_i
        case op
        when ?+
            ans += x
            x = y
        when ?-
            ans += x
            x = -y
        when ?*
            x *= y
        when ?/
            x = x.fdiv(y).to_i
        end
    end
    ans += x
end

解答3

Java 和 JavaScript

分類

C++11

  • 在 OJ 中 C++98 支持得最廣泛

    • 出于速度和輸出格式的考慮包颁,用 printf
    • 目前 LeetCode 中用的是 C++11
  • LeetCode 的有些題目是針對(duì) C++/Java 設(shè)計(jì)的

  • C 中字符串指針在 C++ 中只讀時(shí)可以使用,可以轉(zhuǎn)換為用下標(biāo)

    • 數(shù)組也可以用指針压真,vector 只能用下標(biāo)了娩嚼。
    • C 的字符串后綴是遞歸的數(shù)據(jù)結(jié)構(gòu)
  • 比 C++98 多了 hashtable

    • 有的情況可以用排序
      • 二分法查找
      • 重復(fù)元素相鄰排列
    • 或者用數(shù)組
      • key 少的時(shí)候用下標(biāo)
      • 線性探測(cè)法,特別是不刪滴肿,有限的時(shí)也挺簡(jiǎn)單
  • vector盡量預(yù)先分配大小

  • 有 move 之后可以直接返回 vector 了

  • 比 Java 多了引用岳悟,鏈表問題中 next 的指針可以轉(zhuǎn)換為添加一個(gè)頭節(jié)點(diǎn)

  • 和 Python 相比,有大括號(hào)和分號(hào)

  • 內(nèi)存管理泼差,C++ 沒有 Java 的 GC贵少,相比 C 有 C++ 可以利用作用域

    • 算法題可以利用程序結(jié)束釋放所有內(nèi)存
  • IO 函數(shù) C 比 C++ 快,所以為了充分利用運(yùn)行時(shí)間堆缘,盡量用 C 的

  • 死循環(huán)或者復(fù)雜度太高會(huì)超時(shí)滔灶,下標(biāo)越界或空指針會(huì)運(yùn)行時(shí)錯(cuò)誤

    • 越界錯(cuò)誤有時(shí)候本地會(huì)繼續(xù)運(yùn)行會(huì)未報(bào)錯(cuò)
  • STL

    • C 的 string,qsort套啤,bsearch
  • 假設(shè) Accepted 的解答為結(jié)果正確的解答

    • LeetCode 有的題目在提交后會(huì)又有改動(dòng)
    • 原先 C++ 參數(shù)傳數(shù)組改為用 STL
    • 有個(gè)解答原來不超時(shí)的變得超時(shí)了
  • freebsd 可以看一些標(biāo)準(zhǔn)庫的實(shí)現(xiàn)

  • 感覺最初 LeetCode 是一個(gè)可以刷題的 Blog

  • 提交結(jié)果

    • Runtime Error 越界,爆棧萄涯,空指針
      • 后來開始返回錯(cuò)誤信息了绪氛。。涝影。
    • Time Limit Exceeded 復(fù)雜度枣察,死循環(huán)
  • 參考資料

注意

  • 考慮邊界情況和異常情況
    • 遞歸溢出
  • 自行設(shè)計(jì)測(cè)試用例叛赚,更多情況不像 LeetCode 有提供的可以依賴
  • 死循環(huán)的時(shí)候 Debug
  • 使用 printf scanf
  • 分析題干中的要求,運(yùn)用基本的模型稽揭,分解為步驟的組合
    • 有時(shí)候題目對(duì)輸入有限定
  • 用符合題目要求的俺附,比較好實(shí)現(xiàn)的解答就可以了
    • .size() 為 unsigned,-1 會(huì)不對(duì)

整數(shù)

  • 32位補(bǔ)碼有符號(hào)整數(shù)范圍 $[-2{31},2{31}-1]$ 溪掀,最小負(fù)數(shù)取相反數(shù)會(huì)溢出
  • 在 C 中負(fù)數(shù)取模為負(fù)數(shù)事镣,不同語言有不同規(guī)則
  • 負(fù)數(shù)右移是除以2向下取整數(shù),除法是向零取整數(shù)揪胃。
  • 有符號(hào)璃哟,無符號(hào)位移

數(shù)組/鏈表

  • 數(shù)組和鏈表都可以按順序訪問

    • 數(shù)組還可以按下標(biāo)隨機(jī)讀寫
    • 鏈表有節(jié)點(diǎn)指針變換的問題
  • 插入排序,選擇排序

鏈表

  • 有時(shí)候可以構(gòu)建一個(gè)額外的頭結(jié)點(diǎn)
  • 注意元素個(gè)數(shù)為 0, 1, 2 的情況

棧只嚣,隊(duì)列

  • 可以用數(shù)組和鏈表實(shí)現(xiàn)

二叉樹

  • 遞歸遍歷能應(yīng)對(duì)大部分問題

  • 有些狀態(tài)機(jī)可以作為圖

  • 深度優(yōu)先搜索用 Stack沮稚,廣度優(yōu)先搜索用 Queue

    • 取出元素時(shí)處理
    • 將相鄰節(jié)點(diǎn)插入
      • 有環(huán)圖已搜索過的相鄰節(jié)點(diǎn)不再插入
  • 最短路徑

    • 舉例為 1 時(shí) 變成廣度優(yōu)先搜索
    • 使用優(yōu)先級(jí)隊(duì)列

查找

  • 二分查找

排序

遞歸/回溯

  • 典型問題
    • 八皇后
    • 排列組合
    • 深度優(yōu)先搜索
  • 短路可以通過檢查返回值快速返回
  • 遞歸用棧寫成迭代形式,并不能降低復(fù)雜度册舞。
    • 對(duì)提交代碼的結(jié)果沒有影響蕴掏,除非題目對(duì)實(shí)現(xiàn)方案有特定要求

邏輯/搜索

排列組合

  • 使用回溯法解答,通常寫成遞歸形式
  • 集合是無序的
  • 全排列中升序的序列構(gòu)成組合
  • 有重復(fù)元素時(shí)调鲸,重復(fù)元素的順序改變同一個(gè)排列
  • 集合元素可以用轉(zhuǎn)換為用下標(biāo)(索引)表示

動(dòng)態(tài)規(guī)劃

重疊

字符串

  • 作為數(shù)組問題處理
  • 實(shí)現(xiàn) strstr 函數(shù)

質(zhì)數(shù)

  • 因式分解

C 語言

有些 C 語言的問題沒在數(shù)據(jù)結(jié)構(gòu)書中出現(xiàn)盛杰,也有出現(xiàn)的

  • memmove
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市藐石,隨后出現(xiàn)的幾起案子即供,更是在濱河造成了極大的恐慌,老刑警劉巖于微,帶你破解...
    沈念sama閱讀 206,013評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件逗嫡,死亡現(xiàn)場(chǎng)離奇詭異青自,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)驱证,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,205評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門延窜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人抹锄,你說我怎么就攤上這事逆瑞。” “怎么了伙单?”我有些...
    開封第一講書人閱讀 152,370評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵获高,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我吻育,道長(zhǎng)念秧,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,168評(píng)論 1 278
  • 正文 為了忘掉前任布疼,我火速辦了婚禮出爹,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘缎除。我一直安慰自己,他們只是感情好总寻,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,153評(píng)論 5 371
  • 文/花漫 我一把揭開白布器罐。 她就那樣靜靜地躺著,像睡著了一般渐行。 火紅的嫁衣襯著肌膚如雪轰坊。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,954評(píng)論 1 283
  • 那天祟印,我揣著相機(jī)與錄音肴沫,去河邊找鬼。 笑死蕴忆,一個(gè)胖子當(dāng)著我的面吹牛颤芬,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播套鹅,決...
    沈念sama閱讀 38,271評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼站蝠,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了卓鹿?” 一聲冷哼從身側(cè)響起菱魔,我...
    開封第一講書人閱讀 36,916評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎吟孙,沒想到半個(gè)月后澜倦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體聚蝶,經(jīng)...
    沈念sama閱讀 43,382評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,877評(píng)論 2 323
  • 正文 我和宋清朗相戀三年藻治,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了碘勉。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 37,989評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡栋艳,死狀恐怖恰聘,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情吸占,我是刑警寧澤晴叨,帶...
    沈念sama閱讀 33,624評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站矾屯,受9級(jí)特大地震影響兼蕊,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜件蚕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,209評(píng)論 3 307
  • 文/蒙蒙 一孙技、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧排作,春花似錦牵啦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,199評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至衫生,卻和暖如春裳瘪,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背罪针。 一陣腳步聲響...
    開封第一講書人閱讀 31,418評(píng)論 1 260
  • 我被黑心中介騙來泰國(guó)打工彭羹, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人泪酱。 一個(gè)月前我還...
    沈念sama閱讀 45,401評(píng)論 2 352
  • 正文 我出身青樓派殷,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親墓阀。 傳聞我的和親對(duì)象是個(gè)殘疾皇子愈腾,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,700評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容