寒假LeetCode打卡

文章目录

链表专题

LeetCode 19. Remove Nth Node From End of List

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        //因为头结点可能会改变,所有建立了一个虚拟结点,不需要特判
        auto dummy = new ListNode(-1);
        dummy->next = head;

        //建立了一个快慢指针
        auto first = dummy, second = dummy;
        //快指针先走n步
        while(n--) first = first->next;
        //快慢指针一块走,知道快指针走到了空指针了
        while(first->next)
        {
            first = first->next;
            second = second->next;
        }
        //建立连接关系
        second->next = second->next->next;
        return dummy->next;
    }
};

LeetCode 83. Remove Duplicates from Sorted List

/**
 * 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) {
        auto cur = head;
        while(cur)
        {
            //这里有两种情况,一是相同
            if(cur->next && cur->next->val == cur->val)
            {
                cur->next = cur->next->next;
            }
            //第二种情况就是不同拉
            else
            {
                cur = cur->next;
            }
        }
        return head;
    }
};

LeetCode 206. Reverse Linked List

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if(!head) return NULL;

        auto a = head, b = head->next;
        while(b)
        {
            auto c = b->next;
            b->next = a;
            a = b, b = c;
        }
        head->next = NULL;
        return a;
    }
};

LeetCode 92. Reverse Linked List II

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
//不明觉厉
class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int m, int n) {
        if(m == n) return head;

        auto dummy = new ListNode(-1);
        dummy->next = head;

        auto a = dummy, d = dummy;

        for(int i = 0; i < m - 1; i++) a = a->next;
        for(int i = 0; i < n; i++) d = d->next;

        auto b = a->next, c = d->next;

        for(auto p = b, q = b->next; q != c;)
        {
            auto o = q->next;
            q->next = p;
            p = q, q = o;
        }

        b->next = c;
        a->next = d;

        return dummy->next;      
    }
};

LeetCode 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)return NULL;

        //首先是计算链表的长度是多少呢
        int n = 0;
        for(auto p = head; p; p = p->next)n++;

        //这里旋转n次是不变的,所以是个坑,需要求余
        k %= n;
        //这里的快慢指针也是和之前的题目是一样的
        auto first = head, second = head;
        while(k--) first = first->next;
        while(first->next)
        {
            first = first->next;
            second = second->next;
        }

        //这里再画个图,然后连连线
        first->next = head;
        head = second->next;
        second->next = NULL;

        return head;
    }
};

LeetCode 143. Reorder List

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    void reorderList(ListNode* head) {
        if(!head || !head->next || !head->next->next) return;
        ListNode* dummy = new ListNode(0);
        dummy->next = head;
        while(head->next && head->next->next)
        {
            ListNode* tail = head;
            while(tail->next->next) tail = tail->next;
            tail->next->next = head->next;
            head->next = tail->next;
            tail->next = NULL;
            head = head->next->next;
        }
    }
};

LeetCode 21. Merge Two Sorted Lists

/**
 * 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 *dummy = new ListNode(0);
        ListNode *cur = dummy;
        //比较大小
        while(l1 != NULL && l2 != NULL)
        {
            if(l1->val < l2->val)
            {
                cur->next = l1;
                l1 = l1->next;
            }
            else
            {
                cur->next = l2;
                l2 = l2->next;
            }
            cur = cur->next;
        }
        //将剩余的接到后边
        cur->next = (l1 != NULL ? l1:l2);
        return dummy->next;
    }
};

LeetCode 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 {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        //这题的思路非常巧妙,a+b+c
        auto p = headA, q = headB;
        while(p != q)
        {
            if(p) p = p->next;
            else p = headB;
            if(q) q = q->next;
            else q = headA;
        }
        return p;
    }
};

LeetCode 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:
    //用两个指针从头开始扫描,第一个指针每次走一步,第二个指针每次走两步。
    //如果走到null,说明不存环,否则如果两个指针相遇,则说明存在环
    bool hasCycle(ListNode *head) {
        if(!head || !head->next) return 0;
        ListNode *first = head, *second = first->next;

        while(first && second)
        {
            if(first == second) return true;
            first = first->next;
            second = second->next;
            if(second) second = second = second->next;
        }
        return false;
    }
};

LeetCode 147. Insertion Sort List

/**
 * 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 *dummy = new ListNode(-1);
        while(head)
        {
            ListNode *next = head->next;
            ListNode *p = dummy;
            while(p->next && p->next->val <= head->val) p = p->next;

            head->next = p->next;
            p->next = head;

            head = next;
        }
        return dummy->next;
    }
};

LeetCode 138. Copy List with Random Pointer

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* next;
    Node* random;

    Node(int _val) {
        val = _val;
        next = NULL;
        random = NULL;
    }
};
*/
class Solution {
public:
    unordered_map<Node*, Node*> visHash;
    Node* copyRandomList(Node* head) {
        if(!head)
            return NULL;
        if(visHash.count(head))
            return visHash[head];
        Node* root = new Node(head->val, NULL, NULL);
        visHash[head] = root;
        root->next = copyRandomList(head->next);
        root->random = copyRandomList(head->random);
        return root;
    }
};

LeetCode 142. Linked List Cycle II

/**
 * 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(slow)
        {
            fast = fast->next;
            slow = slow->next;
            if(slow) slow = slow->next;
            else break;

            if(fast == slow)
            {
                slow = head;
                while(slow != fast)
                {
                    fast = fast->next;
                    slow = slow->next;
                }
                return slow;
            }
        }
        return NULL;
    }
};

LeetCode 148. Sort List

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* sortList(ListNode* head) {
        int n = 0;
        for (ListNode *p = head; p; p = p->next) n ++ ;

        ListNode *dummy = new ListNode(-1);
        dummy->next = head;
        for (int i = 1; i < n; i *= 2)
        {
            ListNode *begin = dummy;
            for (int j = 0; j + i < n; j += i * 2)
            {
                ListNode *first = begin->next, *second = first;
                for (int k = 0; k < i; k ++ )
                    second = second->next;
                int f = 0, s = 0;
                while (f < i && s < i && second)
                    if (first->val < second->val)
                    {
                        begin = begin->next = first;
                        first = first->next;
                        f ++ ;
                    }
                    else
                    {
                        begin = begin->next = second;
                        second = second->next;
                        s ++ ;
                    }

                while (f < i)
                {
                    begin = begin->next = first;
                    first = first->next;
                    f ++ ;
                }
                while (s < i && second)
                {
                    begin = begin->next = second;
                    second = second->next;
                    s ++ ;
                }

                begin->next = second;
            }
        }

        return dummy->next;
    }
};

LeetCode 146. LRU Cache

class LRUCache {
public:
    struct Node{
        int key;
        Node *prev, *nxt;
        Node(int k)
        {
            key = k;
            prev = nxt = nullptr;
        }
    };

    int c, tot;
    Node *head, *tail;
    unordered_map<int, pair<int, Node*>> dic;

    LRUCache(int capacity) {
        tot = 0;
        c = capacity;
        Node *dummy1 = new Node(-1);
        Node *dummy2 = new Node(-1);
        head = dummy1;
        tail = dummy2;

        head->nxt = tail;
        tail->prev = head;
    }

    int get(int key) {
        if(dic.find(key) == dic.end())
            return -1;
        Node *node = dic[key].second;
        node->prev->nxt = node->nxt;
        node->nxt->prev = node->prev;

        node->nxt = tail;
        node->prev = tail->prev;

        tail->prev->nxt = node;
        tail->prev = node;
        return dic[key].first;
    }

    void put(int key, int value) {
        if(dic.find(key) != dic.end())
        {
            dic[key].first = value;
            Node *node = dic[key].second;
            node->prev->nxt = node ->nxt;
            node->nxt->prev = node ->prev;

            node->nxt = tail;
            node->prev = tail->prev;

            tail->prev->nxt = node;
            tail->prev = node;
        }
        else
        {
            if(tot == c)
            {
                Node *node = head->nxt;
                dic.erase(node->key);
                head->nxt = node->nxt;
                node->nxt->prev = head;
                delete node;
                tot--;
            }
            Node *node = new Node(key);
            dic[key] = make_pair(value, node);
            node->nxt = tail;
            node->prev = tail->prev;

            tail->prev->nxt = node;
            tail->prev = node;
            tot++;
        }
    }
};

/**
 * Your LRUCache object will be instantiated and called as such:
 * LRUCache* obj = new LRUCache(capacity);
 * int param_1 = obj->get(key);
 * obj->put(key,value);
 */

DFS+回溯专题

LeetCode 17. Letter Combinations of a Phone Number

class Solution {
public:

// state = {""}
// for 每个数字
//     for c = 当前数字的所有备选字母
//         for s = state中的所有字符串
//             s += c

    string chars[8] = {"abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
    vector<string> letterCombinations(string digits) {
        if(digits.empty()) return vector<string>();

        vector<string> state(1, "");
        for(auto u : digits)
        {
            vector<string> now;
            for(auto c : chars[u - '2'])
                for(auto s : state)
                    now.push_back(s + c);
            state = now;
        }
        return state;
    }
};

LeetCode 46. Permutations

class Solution {
public:
    int n;
    //用来标记某个数字是否用了
    vector<bool> st;
    //存储最终的答案
    vector<vector<int> > ans;
    //存储当前的答案
    vector<int> path;

    vector<vector<int>> permute(vector<int>& nums) {
        //初始化
        n = nums.size();
        st = vector<bool>(n);

        //深搜+回溯
        dfs(nums, 0);
        return ans;
    }

    void dfs(vector<int>& nums, int u)
    {
        //达到了终止条件
        if(u == n)
        {
            ans.push_back(path);
            return;
        }


        for(int i = 0; i < n; i++)
        {
            if(!st[i])
            {
                //标记现场
                st[i] = true;
                path.push_back(nums[i]);
                dfs(nums, u + 1);
                //恢复现场
                path.pop_back();
                st[i] = false;
            }
        }
    }
};

LeetCode 47. Permutations II

class Solution {
public:
    //这里用全局,值引用,这样就不用重复赋值
    int n;
    //答案
    vector<vector<int> > ans;
    //当前枚举的路径
    vector<int> path;
    //标记数组
    vector<bool> st;

    vector<vector<int>> permuteUnique(vector<int>& nums) {
        //初始化
        n = nums.size();
        st = vector<bool>(n);
        path = vector<int>(n);

        //这里通过排序,使得相同的数字排在一块了,对于相同的数字人为规定一个顺序
        sort(nums.begin(), nums.end());

        dfs(nums, 0, 0);

        return ans;
    }

    void dfs(vector<int>& nums, int u, int start)
    {
        //终止条件
        if(u == n)
        {
            ans.push_back(path);
            return;
        }

        //是否是相同的数字,如果是则接着找
        for(int i = start; i < n; i++)
        {
            if(!st[i])
            {
                st[i] = true;
                path[i] = nums[u];
                dfs(nums, u + 1, u + 1 < n && nums[u+1] == nums[u] ? i : 0);
                st[i] = false;
            }
        }
    }
};

LeetCode 78. Subsets

class Solution {
public:
    vector<vector<int>> subsets(vector<int>& nums) {
        //这里存答案
        vector<vector<int> > res;
        //每个数字有两种状态,所以一共有1 << nums.size()中状态,然后填充答案即可
        for(int i = 0; i < 1 << nums.size(); i++)
        {
            vector<int> now;
            for(int j = 0; j < nums.size(); j++)
            {
                if(i >> j & 1)
                    now.push_back(nums[j]);
            }
            res.push_back(now);
        }
        return res;
    }
};

LeetCode 90. Subsets II

class Solution {
public:
    //常规操作,变量
    vector<vector<int> > ans;
    vector<int> path;

    vector<vector<int>> subsetsWithDup(vector<int>& nums) {
        //排个序,这样相同的数字会排在一块
        sort(nums.begin(), nums.end());
        dfs(nums, 0);
        return ans;
    }

    void dfs(vector<int>& nums, int u)
    {
        //终止条件
        if(u == nums.size())
        {
            ans.push_back(path);
            return;
        }

        //这里不一样了,有多少个重复的数字
        int k = 0;
        while(u + k < nums.size() && nums[u + k] == nums[u])k++;
        for(int i = 0; i <= k; i ++)
        {
            dfs(nums, u + k);
            path.push_back(nums[u]);
        }
        for(int i = 0; i <= k; i++)path.pop_back();
    }
};

LeetCode 39. Combination Sum

class Solution {
public:
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        vector<vector<int>> res;
        vector<int> vec;
        dfs(candidates, 0, 0, target, vec, res);
        return res;
    }

    void dfs(vector<int>& candidates, int cur, int n, int target, vector<int>&vec, vector<vector<int>>&res)
    {
        if(cur >= target)
        {
            if(cur == target)
                res.push_back(vec);
            return;
        }
        for(int i = n; i < candidates.size(); i++)
        {
            vec.push_back(candidates[i]);
            dfs(candidates, cur+candidates[i], i, target, vec, res);
            vec.pop_back();
        }
    }
};

LeetCode 40. Combination Sum II

class Solution {
public:
    vector<vector<int>> ans;
    vector<int> path;

    void dfs(vector<int> &a, int sum, int start)
    {
        if(sum < 0) return;
        if(sum == 0) ans.push_back(path);
        for(int i = start; i < a.size(); i++)
        {
            if(i > start && a[i] == a[i - 1])
                continue;
            path.push_back(a[i]);
            dfs(a, sum - a[i], i+1);
            path.pop_back();    
        }
    }

    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        sort(candidates.begin(), candidates.end());
        dfs(candidates, target, 0);
        return ans;
    }
};

LeetCode 216. Combination Sum III

class Solution {
public:
    vector<vector<int> > ans;
    vector<int> path;

    vector<vector<int>> combinationSum3(int k, int n) {
        dfs(k, 1, n);
        return ans;
    }

    void dfs(int k, int start, int n)
    {
        if(!k)
        {
            if(!n) ans.push_back(path);
            return;
        }

        for(int i = start; i <= 10 - k; i++)
        {
            path.push_back(i);
            dfs(k - 1, i + 1, n - i);
            path.pop_back();
        }
    }
};

LeetCode 22. Generate Parentheses

class Solution {
public:
    vector<string> res;
    void solve(int l, int r, int n, string cur)
    {
        if(l == n && r == n)
        {
            res.push_back(cur);
            return;
        }

        if(l < n)
            solve(l + 1, r, n, cur + "(");
        if(r < l)
            solve(l, r + 1, n, cur + ")");
    }

    vector<string> generateParenthesis(int n) {
        if(n == 0)
            return res;
        solve(0, 0, n, "");
        return res;
    }
};

LeetCode 473. Matchsticks to Square

class Solution {
public:
// 这题是裁剪的经典题目:
// 首先是依次构造正方的每条边
// 剪枝:
// 1.从大到小枚举所有边
// 2.每条边内部的木棒长度规定成从大到小
// 3.如果当前木棒拼接失败,则跳过接下来所有长度相同的木棒
// 4.如果当前木棒拼接失败,且是当前边的第一个,则直接剪掉当前分支
// 5.如果当前木棒拼接失败,且是当前边的最后一个,则直接剪掉当前分支

    vector<bool> st;

    bool makesquare(vector<int>& nums) {
        int sum = 0;
        for(auto u : nums) sum += u;

        if(!sum || sum % 4) return false;

        sort(nums.begin(), nums.end());

        reverse(nums.begin(), nums.end());

        st = vector<bool>(nums.size());

        return dfs(nums, 0, 0, sum / 4);
    }

    bool dfs(vector<int>& nums, int u, int cur, int length)
    {
        if(cur == length)u++, cur = 0;
        if(u == 4) return true;

        for(int i = 0; i < nums.size(); i++)
        {
            if(!st[i] && cur + nums[i] <= length)
            {
                st[i] = true;
                if(dfs(nums, u, cur + nums[i], length)) return true;
                st[i] = false;
                if(!cur) return false;
                if(cur + nums[i] == length) return false;
                while(i + 1 < nums.size() && nums[i] == nums[i+1]) i++;
            }
        }
        return false;
    }
};

LeetCode 52. N-Queens II

class Solution {
public:
    int ans;
    vector<bool> row, col, diag, anti_diag;

    int totalNQueens(int n) {
        row = col = vector<bool>(n, false);
        diag = anti_diag = vector<bool>(2 * n, false);
        ans = 0;
        dfs(0, 0, 0, n);
        return ans;
    }

    void dfs(int x, int y, int s, int n)
    {
        if (y == n) x ++ , y = 0;
        if (x == n)
        {
            if (s == n) ++ ans;
            return ;
        }

        dfs(x, y + 1, s, n);
        if (!row[x] && !col[y] && !diag[x + y] && !anti_diag[n - 1 - x + y])
        {
            row[x] = col[y] = diag[x + y] = anti_diag[n - 1 - x + y] = true;
            dfs(x, y + 1, s + 1, n);
            row[x] = col[y] = diag[x + y] = anti_diag[n - 1 - x + y] = false;
        }
    }
};

LeetCode 37. Sudoku Solver

class Solution {
public:
    //不明觉厉
    bool row[9][9] = {0}, col[9][9] = {0}, cell[3][3][9] = {0};

    void solveSudoku(vector<vector<char>>& board) {
        for(int i =0 ; i < 9; i++)
        {
            for(int j = 0; j < 9; j++)
            {
                char c = board[i][j];
                if(c != '.')
                {
                    int t = c - '1';
                    row[i][t] = col[j][t] = cell[i / 3][j / 3][t] = true;
                }
            }
        }
        dfs(board, 0, 0);
    }

    bool dfs(vector<vector<char> >& board, int x, int y)
    {
        if(y == 9) x++, y = 0;
        if(x == 9) return true;
        if(board[x][y] != '.') return dfs(board, x, y+1);

        for(int i = 0; i < 9; i++)
        {
            if(!row[x][i] && !col[y][i] && !cell[x / 3][y / 3][i])
            {
                board[x][y] = '1' + i;
                row[x][i] = col[y][i] = cell[x / 3][y / 3][i] = true;
                if(dfs(board, x, y + 1)) return true;
                row[x][i] = col[y][i] = cell[x / 3][y / 3][i] = false;
                board[x][y] = '.';
            }
        }
        return false;
    }
};

LeetCode 282. Expression Add Operators

class Solution {
public:
    vector<string> res;
    string exp;
    int n;

    vector<string> addOperators(string num, int target) {
        n = num.length();
        exp = string(n * 2, ' ');
        dfs(num, target, 0, 0, 0, 0);
        return res;
    }

    void dfs(string &num, int target, int pos, int len, long prev, long cur)
    {
        if(pos == n)
        {
            if(cur == target) res.push_back(exp.substr(0, len));
            return;
        }
        long long next = 0;
        int s = pos, l = len;
        if(s != 0) ++len;
        while(pos < n)
        {
            next = next * 10 + (num[pos] - '0');
            if(num[s] == '0' && pos - s > 0) break;
            if(next > INT_MAX) break;
            exp[len++] = num[pos++];
            if(s == 0)
            {
                dfs(num, target, pos, len, next, next);
                continue;
            }
            exp[l] = '+'; dfs(num, target, pos, len, next, cur + next);
            exp[l] = '-'; dfs(num, target, pos, len, -next, cur - next);
            exp[l] = '*'; dfs(num, target, pos, len, prev*next, cur - prev + prev * next);
        }
    }
};

LeetCode 301. Remove Invalid Parentheses

class Solution {
public:
    //搜索+剪枝
    vector<string> res;
    vector<string> removeInvalidParentheses(string s) {
        int l = 0, r = 0, n = s.length();
        for(int i = 0; i < n; i++)
        {
            if(s[i] == '(') l++;
            if(l == 0 && s[i] == ')') r++;
            else if(s[i] == ')') l--;
        }
        dfs(s, 0, l, r);
        return res;
    }

    bool check(string s)
    {
        int cnt = 0, n = s.length();
        for(int i = 0; i < n; i++)
        {
            if(s[i] == '(') cnt++;
            else if(s[i] == ')') cnt--;
            if(cnt < 0) return false;
        }
        return cnt == 0;
    }

    void dfs(string s, int u, int l, int r)
    {
        if(l == 0 && r == 0)
        {
            if(check(s)) res.push_back(s);
            return;
        }
        int n = s.length();
        for(int i = u; i < n; i++)
        {
            if(s[i] != '(' && s[i] != ')')continue;
            if(i == u || s[i] != s[i - 1])
            {
                string cur = s;
                cur.erase(i, 1);
                if(s[i] == '(' && l > 0) dfs(cur, i, l - 1, r);
                else if(s[i] == ')' && r > 0) dfs(cur, i, l, r - 1);
            }
        }
    }
};

树专题

LeetCode 101. Symmetric Tree

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
//方法一
// 1.两个根节点的值要想相等
// 2.左边的左子树和右边的右子树对称
// 3.左边的右子树和右边的左子树对称
// class Solution {
// public:
//     bool isSymmetric(TreeNode* root) {
//         if(!root) return true;
//         return dfs(root->left, root->right);
//     }

//     bool dfs(TreeNode* p, TreeNode* q)
//     {
//         if(!p || !q) return !p && !q;

//         return p->val == q->val && dfs(p->left, q->right) && dfs(p->right, q->left);
//     }
// };
//方法二
//左边:左中右遍历,右边:右中左进行遍历
//这种方法就是用迭代的方式进行的
class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        if(!root) return true;
        stack<TreeNode*>left, right;
        auto l = root->left, r = root->right;
        while(l || r || left.size() || right.size())
        {
            while(l && r)
            {
                left.push(l), l = l->left;
                right.push(r), r = r->right;
            }

            if(l || r) return false;

            l = left.top(), left.pop();
            r = right.top(), right.pop();

            if(l->val != r->val) return false;

            l = l->right, r = r->left;

        }      
        return true;
    }
};

LeetCode 104. Maximum 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 maxDepth(TreeNode* root) {
        return root ? max(maxDepth(root->left), maxDepth(root->right)) + 1 : 0;
    }
};

LeetCode 145. Binary Tree Postorder 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<int> postorderTraversal(TreeNode* root) {
        vector<int> result, left, right;
        if(!root) return result;

        left = postorderTraversal(root->left);
        for(auto &x:left) result.push_back(x);

        right = postorderTraversal(root->right);
        for(auto &x:right) result.push_back(x);

        result.push_back(root->val);
        return result;
    }
};

LeetCode 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:
    unordered_map<int, int> pos;

    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        int n = preorder.size();
        for(int i = 0; i < n; i++)pos[inorder[i]] = i;

        return dfs(preorder, inorder, 0, n-1, 0, n-1);
    }

    TreeNode* dfs(vector<int>& preorder, vector<int>& inorder, int pl, int pr, int il, int ir)
    {
        if(pl > pr) return NULL;
        int val = preorder[pl];
        int k = pos[val];
        int len = k - il;
        auto root = new TreeNode(val);
        root->left = dfs(preorder, inorder, pl + 1, pl + len, il, k-1);
        root->right = dfs(preorder, inorder, pl + len + 1, pr, k+1, il);
        return root;
    }
};

LeetCode 331. Verify Preorder Serialization of a Binary Tree

class Solution {
public:
    bool ans = true;
    bool isValidSerialization(string preorder) {
        preorder += ',';
        int u = 0;
        dfs(preorder, u);
        return ans && u == preorder.size();
    }

    void dfs(string &preorder, int &u)
    {
        if (u == preorder.size())
        {
            ans = false;
            return;
        }
        if (preorder[u] == '#')
        {
            u += 2;
            return;
        }
        while (preorder[u] != ',') u ++ ; u ++ ;
        dfs(preorder, u);
        dfs(preorder, u);
    }
};

LeetCode 102. Binary Tree Level Order Traversal

if(!root) return res;

    //使用队列进行bfs,也可以用数组去实现
    queue<TreeNode*> q;
    q.push(root);
    while(q.size())
    {
        //队列的长度就是需要输出的长度
        int len = q.size();
        vector<int> level;

        //一方面需要把数值加到队列中,一方面不要忘记了扩展队列
        for(int i = 0; i < len; i++)
        {
            auto t = q.front();
            q.pop();
            level.push_back(t->val);
            if(t->left) q.push(t->left);
            if(t->right) q.push(t->right);
        }

        res.push_back(level);
    }
    return res;

LeetCode 653. Two Sum IV - Input is a BST

/**
 * 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> inorder;

    bool findTarget(TreeNode* root, int k) {
        dfs(root);
        for(int i = 0, j = inorder.size() - 1; i < j; i++)
        {
            while(i < j && inorder[i] + inorder[j] > k) j--;
            if(i < j && inorder[i] + inorder[j] == k) return true;
        }
        return false;
    }

    void dfs(TreeNode *root)
    {
        if(!root) return;
        dfs(root->left);
        inorder.push_back(root->val);
        dfs(root->right);
    }
};

LeetCode 236. Lowest Common Ancestor of a 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) {}
 * };
 */
//这题不是很明白
//如果以root为根的子树中包含p和q,则返回他们最近的公共祖先
//如果只包含p,则返回p
//如果只包含q,则返回q
//如果都不包含,则返回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)return right;
        if(!right)return left;
        return root;
    }
};

LeetCode 543. Diameter 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 ans = 0;
    int diameterOfBinaryTree(TreeNode* root) {
        dfs(root);
        return ans;
    }

    int dfs(TreeNode *root)
    {
        if(!root) return 0;
        auto left = dfs(root->left);
        auto right = dfs(root->right);

        ans = max(ans, left + right);
        return max(left+1, right+1);
    }
};

LeetCode 124. Binary Tree Maximum Path Sum

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
//这题和求树的最大直径是很相似的,dfs返回的不是答案,而是深度
class Solution {
public:
    int ans = INT_MIN;
    int maxPathSum(TreeNode* root) {
        dfs(root);
        return ans;
    }

    int dfs(TreeNode *root)
    {
        if(!root) return 0;

        auto left = dfs(root->left);
        auto right = dfs(root->right);

        ans = max(ans, left + root->val + right);
        return max(0, root->val + max(left, right));
    }
};

LeetCode 87. Scramble String

class Solution {
public:
    bool isScramble(string s1, string s2) {
        if (s1 == s2) return true;
        string ss1 = s1, ss2 = s2;
        sort(ss1.begin(), ss1.end()), sort(ss2.begin(), ss2.end());
        if (ss1 != ss2) return false;
        for (int i = 1; i < s1.size(); i ++ )
        {
            if (isScramble(s1.substr(0, i), s2.substr(0, i))
                    && isScramble(s1.substr(i), s2.substr(i)))
                return true;
            if (isScramble(s1.substr(0, i), s2.substr(s2.size() - i))
                    && isScramble(s1.substr(i), s2.substr(0, s2.size() - i)))
                return true;
        }
        return false;
    }
};

LeetCode 117. Populating Next Right Pointers in Each Node II

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* left;
    Node* right;
    Node* next;

    Node() : val(0), left(NULL), right(NULL), next(NULL) {}

    Node(int _val) : val(_val), left(NULL), right(NULL), next(NULL) {}

    Node(int _val, Node* _left, Node* _right, Node* _next)
        : val(_val), left(_left), right(_right), next(_next) {}
};
*/
class Solution {
public:
    Node* connect(Node* root) {
        if(!root) return root;
        queue<pair<Node*, int>> q;
        if(root->left) q.push(make_pair(root->left, 1));
        if(root->right) q.push(make_pair(root->right, 1));
        int flag = 0;
        Node* temp;
        while(!q.empty())
        {
            int level = q.front().second;
            Node* node = q.front().first;
            q.pop();
            if(node->left) q.push(make_pair(node->left, level+1));
            if(node->right) q.push(make_pair(node->right, level+1));
            if(level == flag)
            {
                temp->next = node;
                temp = node;
            }
            else
            {
                flag = level;
                temp = node;
            }
        }
        return root;
    }
};

LeetCode 99. Recover Binary Search 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:
    void recoverTree(TreeNode* root) {
        TreeNode* first = NULL, *second, *prep = NULL;
        while(root)
        {
            if(!root->left)
            {
                if(prep && prep->val > root->val)
                {
                    if(!first) first = prep, second = root;
                    else second = root;
                }
                prep = root;
                root = root->right;
            }
            else
            {
                TreeNode *p = root->left;
                while(p->right && p->right != root) p = p->right;
                if(!p->right)
                {
                    p->right = root;
                    root = root->left;
                }
                else
                {
                    p->right = NULL;
                    if(prep && prep->val > root->val)
                    {
                        if(!first) first = prep, second = root;
                        else second = root;
                    }
                    prep = root;
                    root = root->right;
                }
            }
        }
        swap(first->val, second->val);
    }
};

LeetCode 337. House Robber III

/**
 * 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:
    unordered_map<TreeNode*, unordered_map<int, int>>f;

    int rob(TreeNode* root) {
        dfs(root);
        return max(f[root][0], f[root][1]);
    }

    void dfs(TreeNode *root)
    {
        if (!root) return;
        dfs(root->left);
        dfs(root->right);
        f[root][1] = root->val + f[root->left][0] + f[root->right][0];
        f[root][0] = max(f[root->left][0], f[root->left][1]) + max(f[root->right][0], f[root->right][1]);
    }
};

动态规划专题(1/2)

LeetCode 53. Maximum Subarray

class Solution {
public:
    //求出所有子段的和的最大值
    //枚举所有的起点和终点
    int maxSubArray(vector<int>& nums) {
        int res = INT_MIN, last = 0;
        for(int i = 0; i < nums.size(); i++)
        {
            int now = max(last, 0) + nums[i];
            res = max(res, now);
            last = now;
        }
        return res;
    }
};

LeetCode 300. Longest Increasing Subsequence

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        int n = nums.size();
        vector<int> f(n);

        for(int i = 0; i < n; i++)
        {
            f[i] = 1;
            for(int j = 0; j < i; j++)
                if(nums[j] < nums[i])
                    f[i] = max(f[i], f[j] + 1);
        }

        int res = 0;
        for(int i = 0; i < n; i++) res = max(res, f[i]);
        return res;
    }
};

LeetCode 72. Edit Distance

class Solution {
public:
    int minDistance(string word1, string word2) {
        int n = word1.size(), m = word2.size();
        vector<vector<int> > f(n + 1, vector<int>(m + 1));
        for(int i = 0; i <= n; i++) f[i][0] = i;
        for(int i = 0; i <= m; i++) f[0][i] = i;
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= m; j++)
            {
                f[i][j] = min(f[i - 1][j], f[i][j - 1]) + 1;
                f[i][j] = min(f[i][j], f[i - 1][j - 1] + (word1[i - 1] != word2[j - 1]));
            }
        return f[n][m];
    }
};

LeetCode 121. Best Time to Buy and Sell Stock

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        if(prices.size() < 2) return 0;
        int profit = 0, low = prices[0];
        for(int i = 1; i < prices.size(); i++)
        {
            profit = max(profit, prices[i] - low);
            low = min(low, prices[i]);
        }
        return profit;
    }
};

LeetCode 122. Best Time to Buy and Sell Stock II

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int sum = 0;
        //遍历一次数组,低进高出,把正的价格相加就是最终的利润
        for(int i = 1; i < prices.size(); i++)
            if(prices[i] > prices[i-1])
                sum += prices[i] - prices[i-1];
        return sum;
    }
};

LeetCode 123. Best Time to Buy and Sell Stock III

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int n = prices.size();
        if(!n) return 0;
        vector<int> f(n, 0);
        int minv = INT_MAX;
        // 从前往后扫描
        for(int i = 0; i < n; i++)
        {
            if(i) f[i] = f[i - 1];
            if(prices[i] > minv)
                f[i] = max(f[i], prices[i] - minv);
            minv = min(minv, prices[i]);
        }
        int res = f[n - 1];
        int maxv = INT_MIN;
        // 从后往前扫描
        for(int i = n - 1; i > 0; i--)
        {
            if(prices[i] < maxv)
                res = max(res, maxv - prices[i] + f[i - 1]);
            maxv = max(maxv, prices[i]);
        }
        return res;
    }
};

LeetCode 188. Best Time to Buy and Sell Stock IV

class Solution {
public:
    int maxProfit(int k, vector<int>& prices) {
        int n = prices.size();
        if( k >= n / 2)
        {
            int res = 0;
            for(int i = 1; i < n; i++)res += max(0, prices[i] - prices[i - 1]);
            return res;
        }

        int f[k + 1], g[k + 1];
        for(int i = 0; i <= k; i++) f[i] = 0, g[i] = INT_MIN;
        for(int cur : prices)
            for(int i = k; i; i--)
            {
                f[i] = max(f[i], g[i] + cur);
                g[i] = max(g[i], f[i - 1] - cur);
            }
        return f[k];
    }
};

LeetCode 309. Best Time to Buy and Sell Stock with Cooldown

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int n = prices.size();
        int f = 0;
        int g = -1000000000;
        int h = -1000000000;
        for(int i = 0; i < n; i++)
        {
            int new_f = max(f,g);
            int new_g = h + prices[i];
            int new_h = max(h, f - prices[i]);
            f = new_f;
            g = new_g;
            h = new_h;
        }
        return max(f,g);
    }
};

LeetCode 198. House Robber

class Solution {
public:
    int rob(vector<int>& nums) {
        int n = nums.size();
        vector<int> f(n+1), g(n+1);
        for(int i = 1; i <= n; i++)
        {
            f[i] = max(f[i - 1], g[i - 1]);
            g[i] = f[i - 1] + nums[i - 1];
        }
        return max(f[n], g[n]);
    }
};

LeetCode 213. House Robber II

class Solution {
public:
    int rob(vector<int>& nums) {
        int n = nums.size();

        if(n == 0) return 0;
        if(n == 1) return nums[0];
        if(n == 2) return max(nums[0], nums[1]);

        int ans = 0, f, g;
        //选择第一个
        f = nums[2], g = 0;
        for(int i = 3; i < n; i++)
        {
            int last_f = f, last_g = g;
            f = last_g + nums[i];
            g = max(last_f, last_g);
        }
        ans = g + nums[0];

        //不选择第一个
        f = nums[1], g = 0;
        for(int i = 2; i < n; i++)
        {
            int last_f = f, last_g = g;
            f = last_g + nums[i];
            g = max(last_f, last_g);
        }
        ans = max(ans, max(f,g));
        return ans;
    }
};

LeetCode 312. Burst Balloons

class Solution {
public:
    int maxCoins(vector<int>& nums) {
        int n = nums.size();
        //在num最前面插入一个1
        nums.insert(nums.begin(), 1);
        //在num最后面插入一个1
        nums.push_back(1);
        vector<vector<int>> dp(n+2, vector<int>(n+2, 0));

        for(int len = 1; len <= n; len++)
            for(int i = 1; i <= n - len + 1; i++)
            {
                int j = i + len - 1;
                for(int k = i; k <= j; k++)
                {
                    dp[i][j] = max(dp[i][j], dp[i][k - 1] + nums[i - 1]*nums[k]*nums[j+1] + dp[k+1][j]);   
                }
            }
        return dp[1][n];
    }
};

LeetCode 96. Unique Binary Search Trees

class Solution {
public:
    int numTrees(int n) {
        vector<int> f(n+1);
        f[0] = 1;
        //f[n]表示n个节点的二叉搜索树共有多少种
        for(int i = 1; i <= n; i++)
        {
            f[i] = 0;
            for(int j = 1; j <= i; j++)
                f[i] += f[j - 1] * f[i - j];
        }
        return f[n];
    }
};

LeetCode 140. Word Break II

class Solution {
public:
    vector<string> ans;
    unordered_map<string, int> dict;

    vector<string> wordBreak(string s, vector<string>& wordDict) {
        for(auto &word : wordDict) dict[word] = 1;
        int n = s.size();
        vector<bool> f(n+1, true);
        for(int i = 1; i <= n; i++)
        {
            f[i] = false;
            for(int j = 0; j < i; j++)
                if(dict[s.substr(j, i - j)] && f[j])
                {
                    f[i] = true;
                    break;
                }
        }

        dfs(f, s, "", n);
        return ans;
    }

    void dfs(vector<bool>&f, string &s, string path, int u)
    {
        if(!u)
        {
            ans.push_back(path.substr(0, path.size() - 1));
            return;
        }

        for(int i = 0; i < u; i++)
            if(dict[s.substr(i, u - i)] && f[i])
                dfs(f, s, s.substr(i, u - i) + ' ' + path, i);
    }
};

LeetCode 10. Regular Expression Matching

class Solution {
public:
    bool isMatch(string s, string p) {
        int n = s.size(), m = p.size();
        s = ' ' + s, p = ' ' + p;
        vector<vector<bool>> f(n + 1, vector<bool>(m + 1));
        for(int i = 0; i <= n; i++)
            for(int j = 0; j <= m; j++)
                if(!i && !j) f[i][j] = true;
                else
                {
                    if(j + 1 <= m && p[j + 1] == '*') continue;
                    if(p[j] != '*')
                    {
                        if(p[j] == '.' || s[i] == p[j])
                            if(i > 0 && j > 0)
                                f[i][j] = f[i - 1][j - 1];
                    }
                    else
                    {
                        if(j >= 2) f[i][j] = f[i][j - 2];
                        if(i > 0 & j > 0)
                        {
                            if(p[j - 1] == '.' || s[i] == p[j - 1])
                                if(f[i - 1][j])
                                    f[i][j] = true;
                        }
                    }
                }
        return f[n][m];
    }
};

字符串专题

LeetCode 38. Count and Say

class Solution {
public:
    //模拟题
    string countAndSay(int n) {
        string s = "1";
        for(int i = 0; i < n-1; i++)
        {
            string ns;
            for(int j = 0; j < s.size(); j++)
            {
                //常用技巧
                int k = j;
                while(k < s.size() && s[k] == s[j])k++;
                ns += to_string(k - j) + s[j];
                j = k - 1;
            }
            s = ns;
        }
        return s;
    }
};

LeetCode 49. Group Anagrams

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        //每一组的特征在于,排序后一样
        unordered_map<string, vector<string> > hash;
        for(auto str : strs)
        {
            string key = str;
            sort(key.begin(), key.end());
            hash[key].push_back(str);
        }

        vector<vector<string> > res;
        for(auto item : hash) res.push_back(item.second);
        return res;
    }
};

LeetCode 151. Reverse Words in a String

class Solution {
public:
    string reverseWords(string s) {
        //首先翻转每一个单词,然后翻转整个句子就能达到这样的效果
        int k = 0;
        for(int i = 0; i < s.size(); i++)
        {
            while(i < s.size() && s[i] == ' ')i++;
            if(i == s.size())break;
            int j = i;
            while(j < s.size() && s[j] != ' ')j++;
            reverse(s.begin() + i, s.begin() + j);
            if(k) s[k++] = ' ';
            while(i < j)s[k++] = s[i++];
        }
        s.erase(s.begin() + k, s.end());
        reverse(s.begin(), s.end());
        return s;
    }
};

LeetCode 165. Compare Version Numbers

class Solution {
public:
    int compareVersion(string s1, string s2) {
        //这里使用双指针进行比较
        int i = 0, j = 0;
        while(i < s1.size() || j < s2.size())
        {
            int x = i, y = j;
            //x, y分别代表每一段的值,这里用到了常用的编码方式,移动指针
            while(x < s1.size() && s1[x] != '.') x++;
            while(y < s2.size() && s2[y] != '.') y++;
            //将字符转化为数字
            int a = i == x ? 0 : atoi(s1.substr(i, x - i).c_str());
            int b = j == y ? 0 : atoi(s2.substr(j, y - j).c_str());
            if(a > b) return 1;
            if(a < b) return -1;
            //移动到下一段
            i = x + 1, j = y + 1;
        }
        return 0;
    }
};

LeetCode 5. Longest Palindromic Substring

class Solution {
public:
    string longestPalindrome(string s) {
        string res;
        //枚举每一个起点,然后向两边扩展
        for(int i = 0; i < s.size(); i++)
        {
            //奇数的情况
            for(int j = i, k = i; j >= 0 && k < s.size() && s[j] == s[k]; j--, k++)
                if(res.size() < k - j + 1)
                    res = s.substr(j, k - j + 1);
            //偶数的情况
            for(int j = i, k = i + 1; j >= 0 && k < s.size() && s[j] == s[k]; j--, k++)
                if(res.size() < k - j + 1)
                    res = s.substr(j, k - j + 1);
        }
        return res;
    }
};

LeetCode 273. Integer to English Words

class Solution {
public:
    string small[20] = {"Zero", "One","Two","Three", "Four","Five","Six","Seven","Eight","Nine","Ten", "Eleven","Twelve","Thirteen","Fourteen","Fifteen","Sixteen","Seventeen","Eighteen","Nineteen"};
    string decade[10] = {"", "", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"};
    string big[4] = {"Billion", "Million", "Thousand", ""};

    //这里把每一个分成一段一段的,3个一组
    string numberToWords(int num) {
        //特判为0
        if(!num) return small[0];

        string res;
        for(int i = 1000000000, j = 0; i > 0; i /= 1000, j++)
        {
            if(num >= i)
            {
                res += get_part(num / i) + big[j] + ' ';
                num %= i;
            }
        }    
        while(res.back() == ' ') res.pop_back();
        return res;
    }

    string get_part(int num)
    {
        string res;
        if(num >= 100)
        {
            res += small[num / 100] + " Hundred ";
            num %= 100;
        }
        if(!num) return res;
        if(num >= 20)
        {
            res += decade[num / 10] + ' ';
            num %= 10;
        }
        if(!num) return res;
        res += small[num] + ' ';
        return res;
    }
};

LeetCode 6. ZigZag Conversion

class Solution {
public:
    string convert(string s, int n) {
        //模拟题
        if(n == 1)return s;
        string res;
        for(int i = 0; i < n; i++)
        {
            if(!i || i == n -1)
            {
                for(int j = i; j < s.size(); j += 2 * (n - 1)) res += s[j];
            }
            else
            {
                for(int j = i, k = 2 * (n - 1) - i; j < s.size() || k < s.size(); j += 2 * (n - 1), k += 2 * (n - 1))
                {
                    if(j < s.size()) res += s[j];
                    if(k < s.size()) res += s[k];
                }
            }
        }
        return res;
    }
};

LeetCode 3. Longest Substring Without Repeating Characters

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        //首先可以想到用hash来判断是不是重复数字
        //之后先暴力枚举,发现双指针能优化
        unordered_map<char, int> hash;
        int res = 0;
        for(int i = 0, j = 0; i < s.size(); i++)
        {
            hash[s[i]]++;
            while(hash[s[i]] > 1)hash[s[j++]]--;
            res = max(res, i - j + 1);
        }
        return res;
    }
};

LeetCode 166. Fraction to Recurring Decimal

class Solution {
public:
    string fractionToDecimal(int _n, int _d) {
        //模拟题,高进度除法
        long long n = _n, d = _d;
        //默认是正数     
        bool minus = false;
        //判断除数和被除数是否是负数,如果是则转化为正数运算
        if(n < 0) minus = !minus, n = -n;
        if(d < 0) minus = !minus, d = -d;

        //首先计算出分数的正数部分      
        string res = to_string(n / d);
        n %= d;
        //这里集中于小数部分
        //边界条件,小数为0
        if(!n)
        {
            if(minus && res != "0") return '-' + res;
            return res;
        }

        res += '.';
        //这里用哈希表存储所有余数对应的商在小数的第几位
        unordered_map<long long, int> hash;
        while(n)
        {
            //如果上一次余数与当前相同,则是循环节,加入跳出循环节
            if(hash[n])
            {
                res = res.substr(0, hash[n]) + '(' + res.substr(hash[n]) + ')';
                break;          
            }   
            else
            {
                hash[n] = res.size();
            }
            //求小数部分
            n *= 10;
            res += to_string(n /d);
            n %= d;
        }
        //加入符号
        if(minus) res = '-' + res;
        return res;
    }
};

LeetCode 208. Implement Trie (Prefix Tree)

class Trie {
public:

    //Trie对应每一个节点的结构体
    struct Node
    {
        bool is_end;
        Node *son[26];
        Node()
        {
            is_end = false;
            for(int i = 0; i < 26; i++) son[i] = NULL;
        }
    }*root;

    /** Initialize your data structure here. */
    Trie() {
        root = new Node();
    }

    //如果为空,则插入,到了结尾处则标记为true
    /** Inserts a word into the trie. */
    void insert(string word) {
        auto p = root;
        for(auto c : word)
        {
            int u = c - 'a';
            if(p->son[u] == NULL)p->son[u] = new Node();
            p = p->son[u];
        }
        p->is_end = true;
    }

    //查找有没有,中间没有直接return,之后看看结尾标记了
    /** Returns if the word is in the trie. */
    bool search(string word) {
        auto p = root;
        for(auto c : word)
        {
            int u = c - 'a';
            if(p->son[u] == NULL)return false;
            p = p->son[u];
        }
        return p->is_end;
    }

    //这个是只要存在就好,不是结尾也是ok的
    /** Returns if there is any word in the trie that starts with the given prefix. */
    bool startsWith(string prefix) {
        auto p = root;
        for(auto c : prefix)
        {
            int u = c - 'a';
            if(p->son[u] == NULL)return false;
            p = p->son[u];
        }
        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);
 */

LeetCode 131. Palindrome Partitioning

class Solution {
public:
    vector<vector<string>> ans;
    vector<string> path;

    vector<vector<string>> partition(string s) {
        dfs("", 0, s);
        return ans;
    }

    //判断当前是否是回文串
    bool check(string &now)
    {
        //直接使用双指针进行判断
        if(now.empty()) return false;
        for(int i = 0, j = now.size() - 1; i < j; i++, j--)
        {
            if(now[i] != now[j])
                return false;   
        }
        return true;
    }


    void dfs(string now, int u, string &s)
    {
        //遍历完成,递归终止,判断方案,加入
        if(u == s.size())
        {   
            if(check(now))
            {
                path.push_back(now);
                ans.push_back(path);
                path.pop_back();    
            }
            return;
        }

        //在相邻的字符之间放置隔板,可以选择放或者不放
        if(check(now))
        {
            path.push_back(now);
            dfs("", u, s);
            path.pop_back();
        }       

        dfs(now + s[u], u + 1, s);
    }       
};

LeetCode 227. Basic Calculator II

class Solution {
public:
    int calculate(string s) {
        //运算符号栈
        stack<char> op;
        //数字栈
        stack<int> num;
        s += "+0";
        for(int i = 0; i < s.size(); i++)
        {       
            if(s[i] == ' ') continue;
            //符号入符号栈,数字入数字栈
            if(s[i] == '*' || s[i] == '/' || s[i] == '+' || s[i] == '-') op.push(s[i]);
            else
            {
                //常用遍历方法
                int j = i;
                while(j < s.size() && s[j] >= '0' && s[j] <= '9') j++;
                num.push(atoi(s.substr(i, j - i).c_str())); 
                i = j - 1;

                if(!op.empty())
                {
                    //优先处理乘除,考虑爆栈问题,元素不超过2
                    if(op.top() == '*' || op.top() == '/')
                    {
                        int y = num.top();
                        num.pop();
                        int x = num.top();
                        num.pop();
                        if(op.top() == '*') num.push(x * y);
                        else num.push(x / y);   
                        op.pop();               
                    }
                    else if(op.size() >= 2)
                    {
                        int z = num.top(); num.pop();
                        int y = num.top(); num.pop();
                        int x = num.top(); num.pop();
                        char op2 = op.top(); op.pop();
                        char op1 = op.top(); op.pop();
                        if(op1 == '+') num.push(x+y), num.push(z);
                        else num.push(x - y), num.push(z);
                        op.push(op2);
                    }
                }       
            }
        }
        num.pop();
        return num.top();
    }
};

LeetCode 30. Substring with Concatenation of All Words

class Solution {
public:

    int check(string s, int begin, int n, int len, int tot, unordered_map<string, int>& wc, vector<int>& ans)
    {
        unordered_map<string, int> vis;
        int count = 0;
        for(int i = begin; i < n - len + 1; i += len)
        {
            string candidate = s.substr(i, len);
            if(wc.find(candidate) == wc.end())
                return i + len;

            while(vis[candidate] == wc[candidate])
            {
                vis[s.substr(begin, len)]--;
                count--;
                begin += len;
            }
            vis[candidate]++;
            count++;
            if(count == tot)
            {
                ans.push_back(begin);
            }
        }
        return n;
    }

    //暴力加枚举,枚举的方式可以按照单词的长度进行枚举
    vector<int> findSubstring(string s, vector<string>& words) {
        vector<int> ans;
        int n = s.length();
        int tot = words.size();
        if(tot == 0) return ans;

        unordered_map<string, int> wc;

        for(int i = 0; i < tot; i++)
            wc[words[i]]++;

        int len = words[0].length();

        for(int offset = 0; offset < len; offset++)
            for(int begin = offset; begin < n; begin = check(s, begin, n, len, tot, wc, ans));
        return ans;     
    }
};

LeetCode 214. Shortest Palindrome

class Solution {
public:
    string shortestPalindrome(string s) {
        string t = s + "#" + string(s.rbegin(), s.rend());
        int n = t.size();
        vector<int> ne(n, 0);

        for(int i = 1, j; i < n; i++)
        {
            j = ne[i - 1];
            while(j && t[i] != t[j]) j = ne[j - 1];
            if(t[i] == t[j]) j++;
            ne[i] = j;      
        }

        string rev = s.substr(ne[n-1]);
        reverse(rev.begin(), rev.end());
        return rev + s;

/*
        string raws = s;
        reverse(s.begin(), s.end());
        s = raws + '#' + s;
        int n = s.size();
        vector<int> next(n+1, 0);
        for(int i = 2, j = 0; i <= n; i++)
        {
            while(j && s[j] != s[j - 1]) j = next[j];
            if(s[j] == s[i - 1]) j++;
            next[i] = j;
        }
        int res = next[n];
        string sup = raws.substr(res);
        reverse(sup.begin(), sup.end());
        return sup + raws;              
*/ 
   }
};

二分与单调队列/栈专题

LeetCode 69. Sqrt(x)

class Solution {
public:
    int mySqrt(int x) {
        int l = 0, r = x;
        while(l < r)
        {
            int mid = (long long)l + r + 1 >> 1;
            if(mid <= x/mid)l = mid;
            else r = mid - 1;
        }
        return r;
    }
};

LeetCode 34. Find First and Last Position of Element in Sorted Array

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        if(nums.empty())return {-1, -1};

        //找到左边界
        int l = 0, r = nums.size() - 1;
        while(l < r)
        {
            int mid = l + r >> 1;
            if(nums[mid] >= target)r = mid;
            else l = mid + 1;
        }

        if(nums[r] != target)return {-1,-1};
        int start = r;

        //找到右边界
        l = 0, r = nums.size() - 1;
        while(l < r)
        {
            int mid = l + r + 1 >> 1;
            if(nums[mid] <= target)l = mid;
            else r = mid - 1;
        }

        int end = r;
        return {start, end};
    }
};

LeetCode 74. Search a 2D Matrix

class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        //判断边界条件
        if(matrix.empty() || matrix[0].empty())return false;

        //用二分去查找,这里有一个换算关系,最后还要判断是不大于
        int n = matrix.size(), m = matrix[0].size();
        int l = 0, r = n * m - 1;
        while(l < r)
        {
            int mid = l + r >> 1;
            if(matrix[mid / m][mid % m] >= target)r = mid;
            else l = mid + 1;
        }

        if(matrix[r / m][r % m] != target)return false;
        return true;
    }
};

LeetCode 240. Search a 2D Matrix II

class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        if(matrix.empty()) return false;
        int row = 0, col = matrix[0].size() - 1;
        //利用规律,从右上角开始找
        while(row < matrix.size() && col >= 0)
        {
            int t = matrix[row][col];
            if(t < target) row++;
            else if(t > target) col--;
            else return true;
        }
        return false;
    }
};

LeetCode 153. Find Minimum in Rotated Sorted Array

class Solution {
public:
    int findMin(vector<int>& nums) {
        int l = 0, r = nums.size() - 1;
        //这里是直接二分,找到分界点
        while(l < r)
        {
            int mid = l + r >> 1;
            if(nums[mid] <= nums.back())r = mid;
            else l = mid + 1;
        }
        return nums[r];
    }
};

LeetCode 162. Find Peak Element

class Solution {
public:
    int findPeakElement(vector<int>& nums) {
        //这题写法简单,但是思路不明白
        int l = 0, r = nums.size() - 1;
        while(l < r)
        {
            int mid = l + r >> 1;
            if(nums[mid] > nums[mid+1]) r = mid;
            else l = mid + 1;
        }
        return r;
    }
};

LeetCode 155. Min Stack

// MinStack minStack = new MinStack();
// minStack.push(-2);
// minStack.push(0);
// minStack.push(-3);
// minStack.getMin();   --> Returns -3.
// minStack.pop();
// minStack.top();      --> Returns 0.
// minStack.getMin();   --> Returns -2.

class MinStack {
public:
    //首先是定义一个栈和一个最小栈
    stack<int> stk, stk_min;

    /** initialize your data structure here. */
    MinStack() {

    }

    //栈里面就随便加,最小栈要比较下,最小栈存的是当前栈中最小的数值
    //如果比较小,则放入栈中,否则则不放入
    void push(int x) {
        stk.push(x);
        if(stk_min.empty()) stk_min.push(x);
        else stk_min.push(min(x, stk_min.top()));
    }

    //弹出的话,就是一起弹处来就可以了
    void pop() {
        stk.pop();
        stk_min.pop();
    }

    //栈顶元素
    int top() {
        return stk.top();
    }

    //栈顶元素,这里要注意,stack和vector函数有点像,但是不一样呢
    int getMin() {
        return stk_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();
 */

LeetCode 496. Next Greater Element I

class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& findNums, vector<int>& nums) {
        stack<int> stk;
        unordered_map<int, int> hash;
        for(int j = nums.size() - 1; j >= 0; j--)
        {
            while(stk.size() && stk.top() <= nums[j]) stk.pop();
            hash[nums[j]] = stk.size() ? stk.top() : - 1;
            stk.push(nums[j]);
        }        
        vector<int> res;
        for(auto x : findNums) res.push_back(hash[x]);
        return res;
    }
};

LeetCode 42. Trapping Rain Water

class Solution {
public:
    int trap(vector<int>& height) {
        int res = 0;
        stack<int> stk;
        for (int i = 0; i < height.size(); i ++ )
        {
            int last = 0;
            while (stk.size() && height[stk.top()] <= height[i])
            {
                int t = stk.top(); stk.pop();
                res += (i - t - 1) * (height[t] - last);
                last = height[t];
            }
            if (stk.size()) res += (i - stk.top() - 1) * (height[i] - last);
            stk.push(i);
        }
        return res;
    }
};

LeetCode 84. Largest Rectangle in Histogram

class Solution {
public:
/*

单调栈:查找每个数左侧第一个比它小的数

单调队列:滑动窗口中的最值

如何枚举处所有的情况呢?
枚举所有柱形的上边界,作为整个矩形的上边界
然后求出左右边界:
1.找出左边离它最近的,比它小的柱形
1.找出右边离它最近的,比它小的柱形
*/
//首先来说是确认上边界,然后找到左右的边界
    int largestRectangleArea(vector<int>& heights) {
        //高度
        int n = heights.size();
        //定义两个左右的边界
        vector<int> left(n), right(n);

        //这里是利用单调栈的性质,是一个升序
        stack<int> stk;
        for(int i = 0; i < n; i++)
        {
            while(stk.size() && heights[stk.top()] >= heights[i])stk.pop();
            if(stk.empty()) left[i] = -1;
            else left[i] = stk.top();
            stk.push(i);        
        }

        while(stk.size()) stk.pop();

        //同理,找到右边界
        for(int i = n - 1; i >= 0; i--)
        {
            while(stk.size() && heights[stk.top()] >= heights[i]) stk.pop();
            if(stk.empty()) right[i] = n;
            else right[i] = stk.top();
            stk.push(i);
        }

        int res = 0;
        for(int i = 0; i < n; i++) res = max(res, heights[i] * (right[i] - left[i] - 1));

        return res;
    }
};

LeetCode 475. Heaters

class Solution {
public:
    int findRadius(vector<int>& houses, vector<int>& heaters) {
        heaters.push_back(INT_MIN), heaters.push_back(INT_MAX);
        sort(heaters.begin(), heaters.end());
        int res = 0;
        for(auto &x : houses)
        {
            int l = 0, r = heaters.size() - 1;
            while(l < r)
            {
                int mid = l + r >> 1;
                if(heaters[mid] >= x) r = mid;
                else l = mid + 1;           
            }
            res = max(res, (int)min(heaters[r] - 0ll - x, x - 0ll - heaters[r-1]));
        }
        return res;
    }
};

LeetCode 4. Median of Two Sorted Arrays

class Solution {
public:
    //原问题难以直接递归求解,所以我们从有序数组中,找出第k小数
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int total = nums1.size() + nums2.size();
        if (total % 2 == 0)
        {
            int left = findKthNumber(nums1, 0, nums2, 0, total / 2);
            int right = findKthNumber(nums1, 0, nums2, 0, total / 2 + 1);
            return (left + right) / 2.0;
        }
        else
        {
            return findKthNumber(nums1, 0, nums2, 0, total / 2 + 1);
        }
    }

    int findKthNumber(vector<int> &nums1, int i, vector<int> &nums2, int j, int k)
    {
        if (nums1.size() - i > nums2.size() - j) return findKthNumber(nums2, j, nums1, i, k);
        if (nums1.size() == i) return nums2[j + k - 1];
        if (k == 1) return min(nums1[i], nums2[j]);
        int si = min(i + k / 2, int(nums1.size())), sj = j + k / 2;
        if (nums1[si - 1] > nums2[sj - 1])
        {
            return findKthNumber(nums1, i, nums2, j + k / 2, k - k / 2);
        }
        else
        {
            return findKthNumber(nums1, si, nums2, j, k - (si - i));
        }
    }
};

LeetCode 239. Sliding Window Maximum

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

LeetCode 456. 132 Pattern

class Solution {
public:
    bool find132pattern(vector<int>& nums) {
        int s3 = INT_MIN;
        stack<int> stk;
        for(int i = nums.size() - 1; i >= 0; i--)
        {
            if(nums[i] < s3) return true;
            while(stk.size() && stk.top() < nums[i])
            {
                s3 = stk.top();
                stk.pop();          
            }
            stk.push(nums[i]);
        }
        return false;
    }
};

哈希表专题

LeetCode 1. Two Sum

class Solution {
public:
    //枚举所有的,如果哈希表中存在则返回
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int, int> hash;
        for(int i = 0; i < nums.size(); i++)
        {
            if(hash.count(target - nums[i])) return {hash[target - nums[i]], i};        
            hash[nums[i]] = i;
        }
        return {-1, -1};
    }
};

LeetCode 454. 4Sum II

class Solution {
public:
    int fourSumCount(vector<int>& A, vector<int>& B, vector<int>& C, vector<int>& D) {
        unordered_map<int, int> hash;
        //建立哈希表,存储数组A和数组B所有数对求和的结果
        for(auto a : A)
            for(auto b : B)
                hash[a + b] ++;
        //枚举数组,查询所有相反数的次数
        int res = 0;
        for(auto c : C)
            for(auto d : D)
                res += hash[- c - d];
        return res;
    }
};

LeetCode 560. Subarray Sum Equals K

class Solution {
public:

    //这里用到了前缀和和hash表进行查找
    int subarraySum(vector<int>& nums, int k) {
        unordered_map<int, int> hash;
        hash[0] = 1;

        int res = 0;
        for(int i = 0, sum = 0; i < nums.size(); i++)
        {
            sum += nums[i];
            res += hash[sum - k];
            hash[sum]++;
        }

        return res;
    }
};

LeetCode 525. Contiguous Array

class Solution {
public:
    int findMaxLength(vector<int>& nums) {
        //这里使用前缀和哈希表一起
        //其中把0转化为-1
        unordered_map<int, int> hash;
        hash[0] = -1;
        int res = 0, s = 0;
        for(int i = 0; i < nums.size(); i++)
        {
            //前缀和
            s += nums[i] * 2 - 1;
            if(hash.count(s))
                res = max(res, i - hash[s]);
            if(!hash.count(s))
                hash[s] = i;
        }
        return res;
    }
};

LeetCode 187. Repeated DNA Sequences

class Solution {
public:
    vector<string> findRepeatedDnaSequences(string s) {
        unordered_map<string, int> hash;

        //插入一个字符串
        //统计字符串出现的次数
        vector<string> res;
        for(int i = 0; i < s.size(); i++)
        {
            //这里substr的第二个参数是长度,要注意
            string str = s.substr(i, 10);
            hash[str]++;
            //当然一个字符串可能出现2次以上,我们只记录一次
            if(hash[str] == 2) res.push_back(str);
        }
        return res;
    }
};

LeetCode 347. Top K Frequent Elements

class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        //首先用哈希表统计所有数出现的次数
        //这里使用计序排序的思想,统计出次数最多的前k个元素的下界
        unordered_map<int, int> hash;
        vector<int> res;
        for(int x : nums) hash[x] ++;
        int n = nums.size();
        vector<int> s(n+1, 0);
        for(auto &p : hash) s[p.second] ++;
        int i = n, t = 0;
        while(t < k) t += s[i--];
        for(auto &p : hash)
            if(p.second > i)
                res.push_back(p.first);
        return res;
    }
};

LeetCode 350. Intersection of Two Arrays II

class Solution {
public:
    vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
        unordered_multiset<int> S;
        vector<int> res;
        for(int x : nums1) S.insert(x);
        for(int x : nums2)
            if(S.count(x))
            {
                res.push_back(x);
                S.erase(S.find(x));
            }
        return res;
    }
};

LeetCode 706. Design HashMap

class MyHashMap {
public:
    /** Initialize your data structure here. */
    const static int N = 20011;

    vector<list<pair<int,int>>> hash;

    MyHashMap() {
        hash = vector<list<pair<int,int>>>(N);
    }

    list<pair<int,int>>::iterator find(int key)
    {
        int t = key % N;
        auto it = hash[t].begin();
        for (; it != hash[t].end(); it ++ )
            if (it->first == key)
                break;
        return it;
    }

    /** value will always be non-negative. */
    void put(int key, int value) {
        int t = key % N;
        auto it = find(key);
        if (it == hash[t].end())
            hash[t].push_back(make_pair(key, value));
        else
            it->second = value;
    }

    /** Returns the value to which the specified key is mapped, or -1 if this map contains no mapping for the key */
    int get(int key) {
        auto it = find(key);
        if (it == hash[key % N].end())
            return -1;
        return it->second;
    }

    /** Removes the mapping of the specified value key if this map contains a mapping for the key */
    void remove(int key) {
        int t = key % N;
        auto it = find(key);
        if (it != hash[t].end())
            hash[t].erase(it);
    }
};

/**
 * Your MyHashMap object will be instantiated and called as such:
 * MyHashMap obj = new MyHashMap();
 * obj.put(key,value);
 * int param_2 = obj.get(key);
 * obj.remove(key);
 */

LeetCode 652. Find Duplicate Subtrees

/**
 * 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 cnt = 0;
    unordered_map<string, int> hash;
    unordered_map<int, int> count;
    vector<TreeNode*> ans;

    //只有前序中序和后序并不能唯一确定一颗树,但是把空节点算上的话就可以
    string dfs(TreeNode* root)
    {
        if(!root) return to_string(hash["#"]);

        //把树进行编码,同时查找           
        auto left = dfs(root->left);
        auto right = dfs(root->right);
        string tree = to_string(root->val) + ',' + left + ',' + right;

        if(!hash.count(tree)) hash[tree] = ++ cnt;
        int t = hash[tree];
        count[t]++;
        if(count[t] == 2) ans.push_back(root);

        return to_string(t);
    }

    vector<TreeNode*> findDuplicateSubtrees(TreeNode* root) {
        hash["#"] = ++cnt;
        dfs(root);
        return ans;
    }
};

LeetCode 290. Word Pattern

class Solution {
public:
    //n组字母和单词的对应关系
    //相同字母对应相同单词
    //不同字母对应不同单词,等价于相同单词对应相同字母
    bool wordPattern(string pattern, string str) {
        stringstream raw(str);
        vector<string> words;
        string word;
        while(raw >> word) words.push_back(word);
        unordered_map<char, string> PS;
        unordered_map<string, char> SP;
        if(pattern.size() != words.size()) return false;
        for(int i = 0; i < words.size(); i++)
        {
            char p = pattern[i];
            string s = words[i];
            if(!PS.count(p)) PS[p] = s;
            if(!SP.count(s)) SP[s] = p;
            if(PS[p] != s || SP[s] != p) return false;
        }
        return true;
    }
};

LeetCode 554. Brick Wall

class Solution {
public:
    int leastBricks(vector<vector<int>>& wall) {
        //不明觉厉
        unordered_map<int, int> hash;
        int res = 0;
        for(auto w : wall)
        {
            int s = 0;
            for(int i = 0; i + 1 < w.size(); i++)
            {
                s += w[i];
                res = max(res, ++hash[s]);
            }
        }
        return wall.size() - res;
    }
};

LeetCode 149. Max Points on a Line

class Solution {
public:
    //先枚举一个定点,然后将其他点按斜率进行分组,分组使用哈希表
    int maxPoints(vector<vector<int>>& points) {
        if(points.empty()) return 0;
        int res = 1;
        for(int i = 0; i < points.size(); i++)
        {
            //竖直线需要单独计算
            //重合点也需要单独计算
            unordered_map<long double, int> map;
            int duplicates = 0, verticals = 1;

            for(int j = i + 1; j < points.size(); j++)
                if(points[i][0] == points[j][0])
                {
                    verticals++;
                    if(points[i][1] == points[j][1]) duplicates++;
                }

            for(int j = i + 1; j < points.size(); j++)
                if(points[i][0] != points[j][0])
                {
                    long double slope = (long double)(points[i][1] - points[j][1]) / (points[i][0] - points[j][0]);
                    if(map[slope] == 0) map[slope] = 2;
                    else map[slope]++;
                    res = max(res, map[slope] + duplicates);
                }
            res = max(res, verticals);
        }
        return res;
    }
};

LeetCode 355. Design Twitter

class Twitter {
public:
    /** Initialize your data structure here. */
    //从一个用户映射到他发的微博列表,包括发布的时间,和发布微博的ID
    unordered_map<int, vector<pair<int, int>>> posts;
    //从一个用户映射到他的关注列表
    unordered_map<int, unordered_set<int>> follows;
    int id = 0;
    Twitter() {

    }

    /** Compose a new tweet. */
    //找到用户的列表,然后插入列表
    void postTweet(int userId, int tweetId) {
        posts[userId].push_back(make_pair(id++, tweetId));
    }

    /** Retrieve the 10 most recent tweet ids in the user's news feed. Each item in the news feed must be posted by users who the user followed or by the user herself. Tweets must be ordered from most recent to least recent. */

    vector<int> getNewsFeed(int userId) {
        vector<pair<int, int>> ps;
        for(auto x : posts[userId]) ps.push_back(x);
        for(auto follow : follows[userId])
            for(auto x : posts[follow])
                ps.push_back(x);
        sort(ps.rbegin(), ps.rend());
        vector<int> res;
        for(int i = 0; i < 10 && i < ps.size(); i++)
            res.push_back(ps[i].second);
        return res;
    }

    /** Follower follows a followee. If the operation is invalid, it should be a no-op. */
    void follow(int followerId, int followeeId) {
        if(followerId != followeeId)
            follows[followerId].insert(followeeId);
    }

    /** Follower unfollows a followee. If the operation is invalid, it should be a no-op. */
    void unfollow(int followerId, int followeeId) {
        follows[followerId].erase(followeeId);
    }
};

/**
 * Your Twitter object will be instantiated and called as such:
 * Twitter* obj = new Twitter();
 * obj->postTweet(userId,tweetId);
 * vector<int> param_2 = obj->getNewsFeed(userId);
 * obj->follow(followerId,followeeId);
 * obj->unfollow(followerId,followeeId);
 */

LeetCode 128. Longest Consecutive Sequence

class Solution {
public:
    int longestConsecutive(vector<int>& nums) {
        int res = 0;
        unordered_map<int, int> tr_left, tr_right;
        for(auto &x : nums)
        {
            int left = tr_right[x - 1];
            int right = tr_left[x + 1];
            tr_left[x - left] = max(tr_left[x -left], left + 1 + right);
            tr_right[x + right] = max(tr_right[x + right], left + 1 + right);
            res = max(res, left + 1 + right);
        }
        return res;
    }
};

动态规划专题(2/2)

LeetCode 120. Triangle

class Solution {
public:
    int minimumTotal(vector<vector<int>>& nums) {
        int n = nums.size();
        vector<vector<long long>> f(2, vector<long long>(n));
        f[0][0] = nums[0][0];
        for(int i = 1; i < n; i++)
            for(int j = 0; j <= i; j++)
            {
                f[i & 1][j] = INT_MAX;
                if(j > 0) f[i & 1][j] = min(f[i & 1][j], f[i - 1 & 1][j - 1] + nums[i][j]);
                if(j < i) f[i & 1][j] = min(f[i & 1][j], f[i - 1 & 1][j] + nums[i][j]);
            }
        long long res = INT_MAX;
        for(int i = 0; i < n; i++) res = min(res, f[n-1 & 1][i]);
        return res;
    }
};

LeetCode 63. Unique Paths II

class Solution {
public:
    //最后一步可以往下走,最后一步也可往右走
    int uniquePathsWithObstacles(vector<vector<int>>& g) {
        int n = g.size(), m = g[0].size();
        vector<vector<long long>> f(n, vector<long long>(m));
        for(int i = 0; i < n; i++)
            for(int j = 0; j < m; j++)
            {
                if(g[i][j]) continue;
                if(!i && !j) f[i][j] = 1;
                if(i > 0) f[i][j] += f[i - 1][j];
                if(j > 0) f[i][j] += f[i][j - 1];
            }

        return f[n-1][m-1];
    }
};

LeetCode 354. Russian Doll Envelopes

class Solution {
public:
    static bool cmp(const vector<int>& a, const vector<int>& b) {
        return a[0] < b[0] || a[0] == b[0] && a[1] > b[1];
    }

    int maxEnvelopes(vector<vector<int>>& envelopes) {
        sort(envelopes.begin(), envelopes.end(), cmp);

        int n = envelopes.size();
        vector<int> dp;
        for (int i = 0; i < n; i ++ ) {
            int x = envelopes[i][1];
            auto it = lower_bound(dp.begin(), dp.end(), x);
            if (it == dp.end()) dp.push_back(x);
            else *it = x;

        }
        return dp.size();   
    }
};

LeetCode 338. Counting Bits

class Solution {
public:
    vector<int> countBits(int num) {
        vector<int> f(num+1);
        f[0] = 0;
        //举例来说111101一共有5个1
        //前面已经计算过了11110,只需要再计算最后一个是不是1就可以了
        for(int i = 1; i <= num; i++)
            f[i] = f[i >> 1] + (i & 1);
        return f;
    }
};

LeetCode 329. Longest Increasing Path in a Matrix

class Solution {
public:
    int n, m;
    vector<vector<int>> f, g;
    int dx[4] = {-1, 0, 1, 0};
    int dy[4] = {0, 1, 0, -1};    

    int dp(int x, int y)
    {
        if(f[x][y] != -1) return f[x][y];
        f[x][y] = 1;
        for(int i = 0; i < 4; i++)
        {
            int a = x + dx[i];
            int b = y + dy[i];
            //结果要比较大
            if(a >= 0 && a < n && b >= 0 && b < m && g[a][b] < g[x][y])
                f[x][y] = max(f[x][y], dp(a, b)+1);
        }
        return f[x][y];
    }

    int longestIncreasingPath(vector<vector<int>>& matrix) {
        if(matrix.empty()) return 0;
        g = matrix;
        n = g.size();
        m = g[0].size();
        f = vector<vector<int>>(n, vector<int>(m, -1));
        int res = 0;
        //枚举每一个点的结果
        for(int i = 0; i < n; i++)
            for(int j = 0; j < m; j++)
                res = max(res, dp(i, j));
        return res;
    }
};

LeetCode 322. Coin Change

class Solution {
public:

    int INF = 1000000000;

    int coinChange(vector<int>& coins, int amount) {
        vector<int> f(amount+1, INF);
        f[0] = 0;
        for(int i = 0; i < coins.size(); i++)
            for(int j = coins[i]; j <= amount; j++)
                f[j] = min(f[j], f[j - coins[i]] + 1);
        if(f[amount] == INF) f[amount] = -1;
        return f[amount];
    }
};

LeetCode 221. Maximal Square

class Solution {
public:
    int maximalSquare(vector<vector<char>>& matrix) {
        if(matrix.empty()) return 0;
        int n = matrix.size();
        int m = matrix[0].size();
        vector<vector<int>> f(n + 1, vector<int>(m + 1, 0));
        int res = 0;
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= m; j++)
                if(matrix[i - 1][j - 1] != '0')
                {
                    f[i][j] = min(f[i - 1][j - 1], min(f[i- 1][j], f[i][j - 1])) + 1;
                    res = max(res, f[i][j]);
                }
        return res * res;
    }
};

LeetCode 576. Out of Boundary Paths

class Solution {
public:
    vector<vector<vector<int>>> f;
    int dx[4] = {-1, 0, 1, 0};
    int dy[4] = {0, 1, 0, -1};
    int mod = 1000000007;

    int findPaths(int m, int n, int N, int i, int j) {
        f = vector<vector<vector<int>>> (m, vector<vector<int>>(n, vector<int>(N+1, -1)));
        return dp(m, n, N, i, j);
    }

    int dp(int m, int n, int k, int x, int y)
    {
        int &v = f[x][y][k];
        if(v != -1) return v;
        v = 0;
        if(!k) return v;
        for(int i = 0; i < 4; i++)
        {
            int a = x + dx[i], b = y + dy[i];
            if(a < 0 || a == m || b < 0 || b == n) v++;
            else v += dp(m, n, k-1, a, b);
            v %= mod;
        }
        return v;
    }
};

LeetCode 91. Decode Ways

class Solution {
public:
    int numDecodings(string s) {
        int n = s.size();
        vector<int> f(n + 1);
        f[0] = 1;
        for(int i = 1; i <= n; i++)
        {
            if(s[i - 1] != '0') f[i] += f[i-1];
            if(i >= 2)
            {
                int t = (s[i - 2] - '0') * 10 + s[i - 1] - '0';
                if(t >= 10 && t <= 26) f[i] += f[i - 2];
            }
        }
        return f[n];
    }
};

LeetCode 264. Ugly Number II

class Solution {
public:
    int nthUglyNumber(int n) {
        vector<int> q;
        q.push_back(1);
        int a = 0, b = 0, c = 0;
        for(int i = 2; i <= n; i++)
        {
            int two = q[a] * 2, three = q[b] * 3, five = q[c] * 5;
            int next = min(two, min(three, five));
            q.push_back(next);
            if(two == next) a++;
            if(three == next) b++;
            if(five == next) c++;
        }
        return q.back();
    }
};

LeetCode 115. Distinct Subsequences

class Solution {
public:
    int numDistinct(string s, string t) {
        int n = s.size(), m = t.size();
        vector<vector<long long>> f(n + 1, vector<long long>(m + 1));

        for(int i = 0; i <= n; i++) f[i][0] = 1;

        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= m; j++)
            {
                f[i][j] = f[i - 1][j];
                if(s[i - 1] == t[j - 1])
                    f[i][j] += f[i - 1][j - 1];
            }
        return f[n][m];
    }
};

LeetCode 132. Palindrome Partitioning II

class Solution {
public:
    int minCut(string s) {
        int n = s.size();
        vector<int> f(n+1);
        vector<vector<bool>> st(n, vector<bool>(n, false));
        for(int i = 0; i < n; i++)
            for(int j = i; j >= 0; j--)
                if(i - j <= 1) st[j][i] = s[j] == s[i];
                else st[j][i] = s[j] == s[i] && st[j + 1][i - 1];

        f[0] = 0;
        for(int i = 1; i <= n; i++)
        {
            f[i] = INT_MAX;
            for(int j = 0; j < i; j++)
                if(st[j][i - 1])
                    f[i] = min(f[i], f[j] + 1);
        }
        return max(0, f[n] - 1);
    }
};

LeetCode 526. Beautiful Arrangement

class Solution {
public:
    int countArrangement(int N) {
        vector<int> f(1 << N, 0);
        f[0] = 1;
        for(int i = 0; i < (1 << N); i++)
        {
            int s = 1;
            for(int j = 0; j < N; j++) s += i >> j & 1;
            for(int j = 1; j <= N; j++)
            {
                if(!(i >> (j - 1) & 1) && (s %j == 0 || j % s == 0))
                    f[i | (1 << (j - 1))] += f[i];
            }
        }
        return f[(1 << N) - 1];
    }
};

LeetCode 486. Predict the Winner

class Solution {
public:
    bool PredictTheWinner(vector<int>& nums) {
        int n = nums.size();
        vector<vector<int>> f(n, vector<int>(n, 0));

        for(int i = 0; i < n; i++)
            f[i][i] = nums[i];

        for(int len = 2; len <= n; len++)
            for(int i = 0; i < n - len + 1; i++)
            {
                int j = i + len - 1;
                f[i][j] = max(-f[i+1][j]+nums[i], - f[i][j-1]+nums[j]);
            }
        return f[0][n - 1] >= 0;
    }
};
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值