c++ Leetcode hot100 超简洁代码(全)

哈希

两数之和

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        int n = nums.size();
        map<int,int> a;
        vector<int> b(2,-1);
        for(int i = 0; i < n; i++){
            if(a.count(target-nums[i])>0){
                b[0] = a[target-nums[i]];
                b[1] = i;
                return b;
            }
            a[nums[i]] = i;
        }
        return b;
    }
};

字母异或位分组

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        int n = strs.size();
        vector<vector<string>> res;
        unordered_map<string,vector<string>> mp;
        for(int i = 0; i < n; i++){
            string str = strs[i];
            sort(str.begin(),str.end());
            mp[str].push_back(strs[i]);
        }
        for(auto ans : mp){
            res.push_back(ans.second);
        }
        return res;
    }
};

最长连续序列

image.png

class Solution {
public:
    int longestConsecutive(vector<int>& nums) {
        if(nums.size() == 0) return 0;
        unordered_map<int,int> mp;
        int res = 1;
        for(auto num : nums){
            if(mp[num] ==0){
                int left = mp[num-1];
                int right = mp[num+1];
                int cur = left + right + 1;
                if(cur > res){
                    res = cur;
                }
                mp[num] = cur;

                mp[num-left] = cur;
                mp[num+right] = cur;
            }
        }
        return res;
    }
};

image.png

class Solution {
public:
    int longestConsecutive(vector<int>& nums) {
        unordered_set<int> hash;
        for(auto x : nums) hash.insert(x);    //放入hash表中
        int res = 0;
        for(auto x : hash)
        {
            if(!hash.count(x-1))
            {
                int y = x;   //以当前数x向后枚举
                while(hash.count(y + 1)) y++;
                res = max(res, y - x + 1);  //更新答案
            }
        }
        return res;
    }
};

双指针

移动零

image.png

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int s = 0;
        for(int i = 0 ; i < nums.size();i++){
            if(nums[i]!=0)nums[s++] = nums[i];
        }
        for(int i = s; i < nums.size();i++){
            nums[i] = 0;
        }
    }
};

image.png

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int n = nums.size(), left = 0, right = 0;
        while (right < n) {
            if (nums[right]) {
                swap(nums[left], nums[right]);
                left++;
            }
            right++;
        }
    }
};

盛最多水的容器

力扣
image.png

class Solution {
public:
    int maxArea(vector<int>& height) {
        int left = 0, right = height.size()-1;
        int res = 0;
        while(left<right){
            if(height[left] < height[right]){
                res = max(res,(right-left)*height[left]);
                left++;
            }else{
                res = max(res,(right-left)*height[right]);
                right--;
            }
        }
        return res;
    }
};

三数之和

image.png

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        int  n = nums.size();
        sort(nums.begin(),nums.end());
        vector<vector<int>> res;
        for(int first = 0; first < n - 2;first++){
            int third = n-1;
            if(first != 0 && nums[first] == nums[first-1]) continue;
            for(int second = first + 1;second < n - 1; second++){
                if(second != first + 1 && nums[second] == nums[second -1]) continue;
                int target = - nums[first]-nums[second];
                
                while(third > second && nums[third] > target) third--;
                
                if(third == second) break;
                
                if(target == nums[third]) 
                    res.push_back({nums[first],nums[second],nums[third]});
            }
        }
        return res;
    }
};

接雨水

acwing是简单
image.png
image.png

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

滑动窗口

无重复字符的最长子串

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int left = 0, n = s.length();
        int res = 0;
        unordered_set<char> st;
        for(int i = 0; i < n; i++){
            while(st.find(s[i])!=st.end()){
                st.erase(s[left]);
                left++;
            }
            res = max(res,i-left+1);
            st.insert(s[i]);
        } 
        return res;
    }
};

image.png

class Solution {
public:
    int lengthOfLongestSubstring(string s){
        if(!s[0])
            return 0;
        int num=0,max=1;
        for(int i=1;s[i]!=0;i++){
            int tmp=1;
            for(int j=num; j<i ;j++){
                if(s[j]==s[i]){
                    num=j+1;
                    break;
                }else{
                    tmp++;
                }
            }
            max=tmp>max?tmp:max;
        }
        return max;
    }   
};

找到字符串中所有字母异位词

image.png

class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        int sLen =s.size(), pLen = p.size();
        if(sLen<pLen) return vector<int>();
        int differ = 0;
        vector<int> ans;
        vector<int> count(26);
        for(int i = 0; i < pLen;++i){
            ++count[s[i] - 'a'];
            --count[p[i] - 'a'];
        }
        for(int i = 0; i < 26; ++i){
            if(count[i]) ++differ;
        }
        if(differ==0) ans.push_back(0);
        for(int i = 0; i < sLen - pLen; ++i){
            if(count[s[i]-'a'] == 1){
                --differ;
            }else if(count[s[i] - 'a'] == 0){
                ++differ;
            }
            --count[s[i]-'a'];
            if(count[s[i+pLen]-'a'] == -1){
                --differ;
            }else if(count[s[i+pLen]-'a'] == 0){
                ++differ;
            }
            ++count[s[i+pLen]-'a'];
            if(differ==0){
                ans.push_back(i+1);
            }
        }
        return ans;

    }
};

子串(滑动窗口2)

和为K的子数组

image.png

class Solution {
public:
    int subarraySum(vector<int>& nums, int k) {
        int n = nums.size();
        int pre = 0,count = 0;
        unordered_map<int,int> mp;
        mp[0] = 1;
        for(auto num : nums){
            pre+=num;
            if(mp.find(pre-k) != mp.end()){
                count += mp[pre-k];
            }
            mp[pre]++;
        }
        return count;
    }
};

滑动窗口的最大值

image.png

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        deque<int> q;
        int left = 0, right = 0;
        vector<int> res;
        for(int i = 0; i < nums.size();i++){
            if(q.size() && (q.front() <= i-k )) 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;
    }
};

最小覆盖子串

时间复杂度O(n)
image.png

class Solution {
public:
    string minWindow(string s, string t) {
        unordered_map<char,int> hs,ht;
        int cnt = 0;
        string res= "";
        for(int i = 0; i < t.size(); i++){
            ht[t[i]]++;
        }
        for(int i = 0, j = 0; i < s.size();i++){
            hs[s[i]]++;
            if(hs[s[i]] <= ht[s[i]]) cnt++;
            while(hs[s[j]] > ht[s[j]]) hs[s[j++]]--;
            if(cnt == t.size()){
                if(res.empty() || i-j+1<res.size()){
                    res = s.substr(j,i-j+1);
                }
            }
        }
        return res;
    }
};

普通数组

最大子数组和

image.png

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int pre = 0,res = nums[0];
        for(auto x : nums){
            pre = max(pre+x,x);
            res = max(pre,res);
        }
        return res;
    }
};

*线段树解法

class Solution {
public:
    struct Status {
        int lSum, rSum, mSum, iSum;
    };

    Status pushUp(Status l, Status r) {
        int iSum = l.iSum + r.iSum;
        int lSum = max(l.lSum, l.iSum + r.lSum);
        int rSum = max(r.rSum, r.iSum + l.rSum);
        int mSum = max(max(l.mSum, r.mSum), l.rSum + r.lSum);
        return (Status) {lSum, rSum, mSum, iSum};
    };

    Status get(vector<int> &a, int l, int r) {
        if (l == r) {
            return (Status) {a[l], a[l], a[l], a[l]};
        }
        int m = (l + r) >> 1;
        Status lSub = get(a, l, m);
        Status rSub = get(a, m + 1, r);
        return pushUp(lSub, rSub);
    }

    int maxSubArray(vector<int>& nums) {
        return get(nums, 0, nums.size() - 1).mSum;
    }
};

合并区间

排序+遍历更新(贪心)

class Solution {
public:
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        sort(intervals.begin(),intervals.end());
        vector<vector<int>> res;
        for(int i = 0; i < intervals.size();){
            int maxEnd = intervals[i][1];
            int j = i + 1;
            while(j < intervals.size() && intervals[j][0] <= maxEnd){
                maxEnd = max(maxEnd,intervals[j][1]);
                ++j;
            }
            res.push_back({intervals[i][0],maxEnd});
            i = j;
        }
        return res;
    }
};

轮转数组

空间复杂度O(1)
image.png

class Solution {
public:
    void reverse(vector<int>& nums,int start,int end){
        while(start < end){
            swap(nums[start++], nums[end--]);

        }
    }
    void rotate(vector<int>& nums, int k) {
        k %=nums.size();
        reverse(nums,0,nums.size()-1);
        reverse(nums,0,k-1);
        reverse(nums,k,nums.size()-1);
    }
};

除自身以外数组的乘积

两次循环

class Solution {
public:
    vector<int> productExceptSelf(vector<int>& nums) {
        int n = nums.size();
        vector<int> ans(n,1);
        for(int i = 1; i < n; ++i){
            ans[i] = ans[i-1] * nums[i-1];
        }
        int test = 1;
        for(int i = n-1; i > 0; --i){
            test *= nums[i];
            ans[i-1] *= test;
        }
        return ans;
    }
};

缺失的第一个整数

遍历一次数组把大于等于1的和小于数组大小的值放到原数组对应位置,然后再遍历一次数组查当前下标是否和值对应,如果不对应那这个下标就是答案,否则遍历完都没出现那么答案就是数组长度加1
image.png

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){
                int pos = nums[i]-1;
                if(nums[i] == nums[pos]) break;
                swap(nums[i],nums[pos]);
            }
        }
        for(int i = 0; i < n; ++i){
            if(nums[i] != i+1)return i+1;
        }
        return n+1;
    }
};

矩阵

矩阵置零

空间复杂度 O(1) ,用两个布尔变量就可以解决。方法就是利用数组的首行和首列来记录 0 值。从数组下标的 A[1][1] 开始遍历,两个布尔值记录首行首列是否需要置0

class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) {
        bool flag1 = false;
        bool flag2 = false;
        int row = matrix.size();
        int col = matrix[0].size();
        for(int i = 0; i < row;++i){
            if(matrix[i][0] == 0){
                flag1 = true;
                break;
            }
        }
        for(int i = 0; i < col; ++i){
            if(matrix[0][i] == 0){
                flag2 = true;
                break;
            }
        }
        for(int i = 1; i < row; ++i){
            for(int j = 1; j < col; ++j){
                if(matrix[i][j] == 0){
                    matrix[0][j] = 0;
                    matrix[i][0] = 0;
                }
            }
        }
        for(int i = 1; i < col; ++i){
            if(matrix[0][i] == 0){
                for(int j = 1; j < row; ++j){
                    matrix[j][i] = 0;
                }
            }
        }
        for(int i = 1; i < row; ++i){
            if(matrix[i][0] == 0){
                for(int j = 1; j < col; ++j){
                    matrix[i][j] = 0;
                }
            }
        }
        if(flag1 == 1){
            for(int i = 0; i < row;++i){
                matrix[i][0] = 0;
            }
        }
        if(flag2 == 1){
            for(int i = 0; i < col; ++i){
                matrix[0][i] = 0;
            }
        }
    }
};

螺旋矩阵

十分麻烦 的 边界情况

class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        vector<int> res;
        int row_begin = 0;
        int col_begin = 0;
        int row = matrix.size()-1;
        int col = matrix[0].size()-1;
        while(true){
            // 向右
            for(int i = col_begin; i <= col; ++i) res.push_back(matrix[row_begin][i]);
            if(++row_begin > row)break;
            // 向下
            for(int i = row_begin; i <= row; ++i) res.push_back(matrix[i][col]);
            if(--col < col_begin)break;
            // 向左
            for(int i = col; i >= col_begin; --i) res.push_back(matrix[row][i]);
            if(--row < row_begin)break;
            // 向上
            for(int i = row; i >= row_begin; --i) res.push_back(matrix[i][col_begin]);
            if(++col_begin > col)break;   
        }
            
        return res;
    }
};

旋转图像

第一眼不会
看一眼答案 woc
image.png

class Solution {
public:
    void rotate(vector<vector<int>>& matrix) {
        int n = matrix.size();
        for(int i = 0; i < n; ++i){
            for(int j = i + 1; j < n; ++j){
                swap(matrix[i][j],matrix[j][i]);
            }
        }
        for(int i = 0; i < n; ++i){
            for(int j = 0; j < n >> 1; ++j){
                swap(matrix[i][j],matrix[i][n - 1 -j]);
            }
        }
    }
};

搜索二维矩阵

找到一个位置 要么加 要么减

class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        int i = matrix.size()-1;
        int j = 0;
        while(i>=0&&j<=matrix[0].size()-1){
            if(matrix[i][j]==target){
                return 1;
            }
            if(matrix[i][j]>target){
                --i;
            }else{
                ++j;
            }
        }
        return false;
    }
};

链表!

相交链表

“朋友们,请一定要珍惜身边的那个 ta 啊!你们之所以相遇,正是因为你走了 ta 走过的路,而 ta 也刚好走了你走过的路。这是何等的缘分!
而当你们携手继续走下去时,你会慢慢变成 ta 的样子,ta 也会慢慢变成你的样子。”

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
       ListNode * a = headA;
       ListNode * b = headB;
       while(true){
           if(a == b){
               return a;
           }
           if(a==nullptr){
               a = headB;
           }else a = a->next;
           if(b==nullptr){
               b = headA;
           }else b = b->next;
       }
       return nullptr;
    }
};

反转链表

啪一下 a了 毕竟背了十来遍了

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* res = nullptr;
        while(head){
            ListNode * temp = head->next;
            head->next = res;
            res = head;
            head = temp;
        }
        return res;
    }
};

回文链表

class Solution {
public:
    ListNode* temp;
    bool isPalindrome(ListNode* head) {
        temp = head;
        return judge(head);
    }
    bool judge(ListNode* head){
        if(head){
            // 递归 head到最后一个位置 开始下面if比较temp head的值,然后head递归后退 temp前进 
            if(!judge(head->next)){
                return false;
            }

            if(head->val != temp->val){
                return false;
            }
            temp = temp->next;

        }
        return true;
    }
};

环形链表

快慢指针

class Solution {
public:
    bool hasCycle(ListNode *head) {
        ListNode * a, *b;
        a = head;
        b = head;
        while(a && b){
            a = a->next;
            if(b->next == nullptr){
                return false;
            }
            b = b->next->next;
            if(a==b){
                return true;
            }
        }
        return false;
    }
};

环形链表2

  1. 走a+nb步一定是在环入口
  2. 第一次相遇时慢指针已经走了nb步 (快指针多走了一倍 多走了n圈追到了)
  3. a = a + nb 所以重置快指针
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode * a, *b;
        a = head;
        b = head;
        int posa= 0,posb = 0;
        while(a && b){
            a = a->next;
            if(b->next == nullptr){
                return nullptr;
            }
            b = b->next->next;
            if(a==b){
                b = head;
                while(a!=b){
                    b = b->next;
                    a = a->next;
                }
                return a;
            }
        }
        return nullptr;
    }
};

合并有序链表

终止条件:当两个链表都为空时,表示我们对链表已合并完成
如何递归:我们判断 l1 和 l2 头结点哪个更小,然后较小结点的 next 指针指向其余结点的合并结果。(调用递归)

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
        if(list1 == nullptr){
            return list2;
        }
        if(list2 == nullptr){
            return list1;
        }
        if(list1->val > list2->val){
            list2->next = mergeTwoLists(list1,list2->next);
            return list2;
        }else{
            list1->next = mergeTwoLists(list1->next,list2);
            return list1;
        }
    }
};

两数相加

class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode* res = new ListNode(0);
        ListNode * cur = res;
        int carry = 0,temp = 0;
        while(l1 || l2){
            temp = carry, carry = 0;
            if(l1){
                temp += l1->val;
                l1 = l1->next;
            }
            if(l2){
                temp += l2->val;
                l2 = l2->next;
            }
            if(temp >=10){
                carry = 1;
            }
            ListNode* t = new ListNode(temp%10);
            cur->next = t;
            cur = t;
        }
        if(carry == 1){
            ListNode* t = new ListNode(1);
            cur->next = t;
            cur = t;
        }
        return res->next;
    }
};

删除链表的倒数第N个结点

快慢指针
快指针先走N步

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* num1 = head;
        ListNode* num2 = head;
        for(int i = 0; i < n; i++){
            num1 = num1->next;
        }
        // 这个必须写 不然无法判断num1->next
        if(!num1){
            return head->next;
        }
        while(num1->next != nullptr){
            num1 = num1->next;
            num2 = num2->next;
        }
        num2->next = num2->next->next;
        return head;
    }
};

两两交换链表中的节点

  1. 调用单元:设需要交换的两个点为 head 和 next,head 连接后面交换完成的子链表,next 连接 head,完成交换
  2. 返回条件是 无法交换的条件
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        if(head == nullptr || head->next == nullptr) return head;

        ListNode * next = head->next;
        
        head->next = swapPairs(next->next);
        next->next = head;

        return next; 
    }
};

K个一组反转链表

反转链表的递归

class Solution {
public:
    ListNode* reverseKGroup(ListNode* head, int k) {
        ListNode* test = head;
        for(int i = 0; i < k; i++){
            if(!test) return head;
            test = test->next;
        }
        ListNode* res = reverseKGroup(test,k);
        for(int i = 0; i < k; i++){
            ListNode* temp = head->next;
            head->next = res;
            res = head;
            head = temp;
        }
        return  res;
    } 
};
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* res = nullptr;
        while(head){
            ListNode * temp = head->next;
            head->next = res;
            res = head;
            head = temp;
        }
        return res;
    }
};

复制带随机指针的链表

class Solution {
public:
    unordered_map<Node*, Node*> cachedNode;

    Node* copyRandomList(Node* head) {
        if (head == nullptr) {
            return nullptr;
        }
        if (!cachedNode.count(head)) {
            
            Node* New1 = new Node(head->val);
            cachedNode[head] = New1;
            // 去递归查表 表里有就返回value 表里无就深拷贝填表
            New1->next = copyRandomList(head->next);
            New1->random = copyRandomList(head->random);
        }
        return cachedNode[head];
    }
};

排序链表

class Solution {
public:
    ListNode* sortList(ListNode* head){
        return sortList(head,nullptr);
    }
    ListNode* sortList(ListNode* head,ListNode * end) {
        if(head==end) return head;
        ListNode* fast = head, *slow = head;
        if(head->next == end){
            head->next = nullptr;
            return head;
        }
        while(fast != end){
            fast = fast->next;
            if(fast != end) fast= fast->next;
            slow = slow->next;
        }
        return mergeTwoLists(sortList(head,slow),sortList(slow,end));
    }
    ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
        if(list1 == nullptr){
            return list2;
        }
        if(list2 == nullptr){
            return list1;
        }
        if(list1->val > list2->val){
            list2->next = mergeTwoLists(list1,list2->next);
            return list2;
        }else{
            list1->next = mergeTwoLists(list1->next,list2);
            return list1;
        }
    }
};

归并排序模板

#include<iostream>
using namespace std;
const int N = 1000010;

int n;
int q[N];
int temp[N];

void merge_sort(int q[],int l , int r)
{
    if(l >= r) return;
    
    int mid = l + r >>1;
    
    merge_sort(q,l,mid),merge_sort(q,mid+1,r);
    
    int k = 0, i = l, j = mid + 1;
    
    while(i<=mid && j<=r)
        if(q[i]<=q[j]) temp[k++] = q[i++];
        else temp[k++] = q[j++];
      
    while(i<=mid) temp[k++] = q[i++];
    while(j<=r) temp[k++] = q[j++];
    for(i = l, j = 0; i<=r;i++,j++)  q[i] = temp[j];
}

int main(){
    scanf("%d",&n);
    for(int i = 0; i < n; i++) scanf("%d",&q[i]);
    merge_sort(q,0,n-1);
    for(int i = 0;i < n; i++) printf("%d ",q[i]);
    return 0;
}

合并K个排序链表

struct cmp{
    bool operator() (const ListNode * a, const ListNode * b){
        return a->val > b->val;
    }
};
class Solution {
public:


    ListNode* mergeKLists(vector<ListNode*>& lists) {
        priority_queue<ListNode*,vector<ListNode*>,cmp> q;
        
        for(int i = 0; i < lists.size(); ++i){
            while(lists[i]){
                q.push(lists[i]);
                lists[i] = lists[i] -> next;
            }
        }
        ListNode * head = new ListNode(0);
        ListNode * cur = head;
        while(!q.empty()){
            cur->next = q.top();
            q.top()->next = nullptr;
            q.pop();
            cur = cur->next;
        }
        return head->next;
    }
};

LRU缓存

背熟

class LRUCache {
public:
    LRUCache(int capacity): _capacity(capacity) {

    }
    
    int get(int key) {
        auto it = _table.find(key);
        if(it != _table.end()){
            _lru.splice(_lru.begin(),_lru,it->second);
            return it->second->second;
        }
        return -1;
    }
    
    void put(int key, int value) {
        auto it = _table.find(key);
        if(it != _table.end()){
            _lru.splice(_lru.begin(),_lru,it->second);
            it->second->second = value;
            return;
        }
        _lru.emplace_front(key,value);
        _table[key] = _lru.begin();
         if (_table.size() > _capacity) {
            _table.erase(_lru.back().first);
            _lru.pop_back();
        }

    }
private:
    unordered_map<int, list<pair<int, int>>::iterator> _table;
    list<pair<int, int>> _lru;
    int _capacity;
};

二叉树的中序遍历

*/
class Solution {
public:
    vector<int> res;
    vector<int> inorderTraversal(TreeNode* root) {
        if(!root) return vector<int>();
        inorderTraversal(root->left);
        res.push_back(root->val);
        inorderTraversal(root->right);
        return res;
    }
};

二叉树的最大深度

class Solution {
public:
    int res = 0;
    void dfs(TreeNode* root, int depth){
        if(!root)return;
        if(depth>res) res = depth;
        if(root->right) dfs(root->right,depth+1);
        if(root->left) dfs(root->left,depth+1);
    }
    int maxDepth(TreeNode* root) {
        dfs(root,1);
        return res;
    }
};

反转二叉树

class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if(!root) return nullptr;
        swap(root->left,root->right);
        if(root->left)invertTree(root->left);
        if(root->right)invertTree(root->right);
        return root;
    }
};

对称二叉树

class Solution {
public:
    bool check(TreeNode *p, TreeNode *q) {
        if (!p && !q) return true;
        if (!p || !q) return false;
        return p->val == q->val && check(p->left, q->right) && check(p->right, q->left);
    }

    bool isSymmetric(TreeNode* root) {
        return check(root, root);
    }
};

二叉树的直径

class Solution {
public:
    int res = 0;
    int dfs(TreeNode* root){
        if(!root) return 0;
        // 下面有多少个点
        int L = dfs(root->left);
        int R = dfs(root->right);
        res = max(res,L+R);
        return max(L,R) + 1;
    }
    int diameterOfBinaryTree(TreeNode* root) {
        int a = dfs(root);
        return res;
    }
};

二叉树的层序遍历

class Solution {
public:
    vector<vector<int>> res;
    void bfs(TreeNode* root){
        queue<TreeNode*> q;
        if(root)q.push(root);
        while(!q.empty()){
            vector<int> ans;
            int n = q.size();
            for(int i = 0; i < n; ++i){
                ans.push_back(q.front()->val);
                if(q.front()->left) q.push(q.front()->left);
                if(q.front()->right) q.push(q.front()->right);
                q.pop();
            }
            res.push_back(ans);
        }
    }
    vector<vector<int>> levelOrder(TreeNode* root) {
        bfs(root);
        return res;
    }
};

验证二叉搜索树

中序遍历

class Solution {
public:
    long long  minval = (long long)INT_MIN - 1;
    bool isValidBST(TreeNode* root) {
        if(!root) return true;


        if(!isValidBST(root->left)) return false;


        if(root->val <= minval) return false;
        minval = root->val;


        return isValidBST(root->right);
    }
};

二叉搜索树中第K小的元素

class Solution {
public: 
    int res = 0;
    int count = 0;
    int k1 = 0;
    void dfs(TreeNode* root){
        if(count == k1 || !root) return;
        dfs(root->left);
        if(++count == k1) res = root->val;
        dfs(root->right);
    }
    int kthSmallest(TreeNode* root, int k) {
        k1 = k;
        dfs(root);
        return res;
    }
};

二叉树的右视图

首先是每次都从右边开始遍历,如果当前深度与放入的数组长度不匹配,证明是第一次来到这个深度,因此右子树有数字就放数字,没有就放左子树

class Solution {
public:
    vector<int> ans;
    void dfs(TreeNode* root,int deepth){
        if (root == NULL){
            return;
        }
        if (deepth > ans.size()) ans.push_back(root->val);
        dfs(root->right,deepth+1);
        dfs(root->left,deepth+1);
    }
    vector<int> rightSideView(TreeNode* root) {
        dfs(root,1);
        return ans;
    }
};

二叉树展开为链表

class Solution {
public:
    // 反向前序遍历
    TreeNode* last = nullptr;
    void flatten(TreeNode* root) {
        if(root == nullptr) return;
        flatten(root->right);
        flatten(root->left);
        root->right = last;
        root->left =nullptr;
        last = root;
    }
};

从前序与中序遍历序列构造二叉树

class Solution {
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        return pre_order(0, inorder.size() - 1, 0, inorder.size() - 1, preorder, inorder);
    }
    
    TreeNode *pre_order(int l1, int r1, int l2, int r2, vector<int> &pre, vector<int> &in) {
        if(l1>r1 || l2>r2) return nullptr;
        TreeNode* root = new TreeNode(pre[l1]);
        int pos = l2;
        while(in[pos]!=pre[l1]) pos++;
        // 左子树的个数
        int len = pos - l2;
        root->left = pre_order(l1+1,l1+len,l2,pos-1,pre,in);
        root->right = pre_order(l1+1+len,r1,pos+1,r2,pre,in);



        return root;
    }
};

路径总和 III

class Solution {
public:
    int cnt = 0;
    int pathSum(TreeNode* root, int targetSum) {
        if(!root) return 0;
        dfs(root,targetSum);
        pathSum(root->left,targetSum);
        pathSum(root->right,targetSum);
        return cnt;
    }
    void dfs(TreeNode* root, long long targetSum){
        if(!root)return;
        targetSum -= root->val;
        if(targetSum==0){cnt++;}//不能返回 还有路径
        dfs(root->left,targetSum);
        dfs(root->right,targetSum);
    }
};

二叉树的最近公共祖先

找到值 然后传递

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(!root) return nullptr;
        if(root == p || root == q)return root;
        TreeNode* l = lowestCommonAncestor(root->left,p,q);
        TreeNode* r = lowestCommonAncestor(root->right,p,q);
        if(l&&r)return root;
        else if(l) return l;
        else return r;
    }
};

二叉树中的最大路径和

class Solution {
public:
    int res = -100000;
    int maxPathSum(TreeNode* root) {
        dfs(root);
        return res;
    }
    int dfs(TreeNode* root){
        if(!root) return 0;

        int L = dfs(root->left);
        int R = dfs(root->right);

        res = max(res,root->val);
        res = max(res,max(L,R)+root->val);
        res = max(res,L+R+root->val);

        return max(max(L,R),0) + root->val;
    }
};

图论

岛屿数量

class Solution {
public:
    int cnt = 0;
    void dfs(vector<vector<char>>& grid,int x,int y){
        if(x < 0 || y < 0 || x > grid.size() - 1 || y > grid[0].size() -1||grid[x][y] == '0'){
            return;
        }
        grid[x][y] = '0';
        dfs(grid,x,y-1);
        dfs(grid,x-1,y);
        dfs(grid,x,y+1);
        dfs(grid,x+1,y);
    }
    int numIslands(vector<vector<char>>& grid) {
        if(grid.size() == 0 || grid[0].size() == 0){
            return 0;
        }
        for(int i = 0; i < grid.size(); ++i){
            for(int j = 0; j < grid[i].size();++j){
                if(grid[i][j] == '1'){
                    dfs(grid,i,j);
                    cnt++;
                }
            }
        }
        return cnt;
    }
};

腐烂的橘子

class Solution {
public:
    typedef pair<int,int> PII;    
    int cnt = 0;
    int dx[4] = {0,1,0,-1};
    int dy[4] = {1,0,-1,0};
    int orangesRotting(vector<vector<int>>& grid) {
        int n1 = grid.size();
        int n2 = grid[0].size();
        queue<pair<int,int>> q;
        for(int i  = 0; i < n1; ++i)
            for(int j = 0; j < n2; ++j){
                if(grid[i][j] == 2) q.push(make_pair(i,j));
                else if(grid[i][j] == 1) cnt++;
            }
        int time = -1;
        while(!q.empty()){
            int n = q.size();
            ++time;
            for(int i = 0; i < n; i++){
                auto temp = q.front();
                q.pop();
                for(int j = 0; j < 4; j++){
                    int nx = temp.first + dx[j];
                    int ny = temp.second + dy[j];
                    if(nx < 0 || ny <  0 || nx > n1-1 || ny > n2-1) continue;
                    if(grid[nx][ny] == 1){
                        grid[nx][ny] =2;
                        q.push(make_pair(nx,ny));
                        cnt--;
                    }
                }
            }
        }
        return cnt ? -1 : max(time,0);
    }
};

课程表

class Solution {
public: 
    bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
        vector<vector<int>> course(numCourses);
        vector<int>  pre(numCourses,0);
        queue<int> q;
        for(auto x : prerequisites){
            course[x[1]].push_back(x[0]);
            ++pre[x[0]];
        }
        int res = numCourses;
        for(int i = 0; i < numCourses; i++){
            if(pre[i] == 0){
                q.push(i);
                --res;
            }
        }
        while(!q.empty()){
            int temp = q.front();
            q.pop();
            for(auto x : course[temp]){
                cout<<pre[x]<<endl;
                if(--pre[x] == 0){
                    q.push(x);
                    --res;
                }
            }
        }
        return res ? false : true;
    }
};

实现 Trie (前缀树)

class Trie {
public:
    // struct Trie {
    //     bool isWord; //该结点是否是一个串的结束
    //     Trie* children[26]; //字母映射表
    // };

    bool isWord; //该结点是否是一个串的结束
    Trie* children[26]; //字母映射表
    Trie() {
        isWord = false;
        memset(children, 0, sizeof(children));
    }
    
    void insert(string word) {
        Trie* p = this;
        for(int i = 0; i < word.length(); i++){
            int c = word[i] - 'a';
            if(p->children[c] == nullptr){
                p->children[c] = new Trie();
            }
            p = p->children[c];
        }
        p->isWord = true;
    }
    
    bool search(string word) {
        Trie* p = this;
        for(int i = 0; i < word.length();i++){
            int c = word[i]  - 'a';
            if(p->children[c] == nullptr){ 
                return false;
            }
            p = p->children[c];
        }
        return p->isWord;
    }
    
    bool startsWith(string prefix) {
        Trie* p = this;
        for(int i = 0;i < prefix.length();i++){
            int c = prefix[i] - 'a';
            if(p->children[c] == nullptr){
                return false;
            }
            p = p->children[c];
        }
        return true;
    }
};

回溯

全排列

class Solution {
public:
    vector<vector<int>> res;
    unordered_map<int,bool> st;
    vector<int> temp;
    vector<vector<int>> permute(vector<int>& nums) {
        for(int i = 0; i < nums.size(); ++i){
            st[nums[i]] = false;
        }
        dfs(nums);
        return res;
    }
    void dfs(vector<int>& nums){
        if(temp.size() == nums.size()){
            res.push_back(temp);
            return;
        }
        for(int i = 0; i < nums.size();++i){
            if(st[nums[i]] == false){
                st[nums[i]] = true;
                temp.push_back(nums[i]);
                dfs(nums);
                temp.pop_back();
                st[nums[i]] = false;
            }
        }
    }
};

子集

class Solution {
public:
    vector<vector<int>> res;
    vector<int> temp;
    vector<vector<int>> subsets(vector<int>& nums) {
        dfs(nums,0);
        return res;
    }
    void dfs(vector<int>& nums,int size){
        if(size == nums.size()){
            res.push_back(temp);
            return;
        }
        temp.push_back(nums[size]);
        dfs(nums,size+1);
        temp.pop_back();
        dfs(nums,size+1);
    }
};

电话号码的字母组合

class Solution {
public:
    string num[10]={"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};   
    vector<string> res;
    vector<string> letterCombinations(string digits) {
        if(digits.size() == 0)return res;
        dfs(digits,0,"");
        return res;
    }
    void dfs(string digits,int size,string temp){
        if(size == digits.size()){
            res.push_back(temp);
            return;
        }
        int curNum = digits[size] - '0'; 
        for(int i = 0; i < num[curNum].size(); ++i){
            string s = temp + num[curNum][i];
            dfs(digits,size+1,s);
        }
    }
};

组合总和

class Solution {
public:
    vector<vector<int>> res;
    vector<int> temp;
    void dfs(vector<int>& candidates, int target,int ii){
        if(target == 0){
            res.push_back(temp);
        }
        for(int i = ii; i < candidates.size();i++){
            if(candidates[i] > target) continue;
            temp.push_back(candidates[i]);
            dfs(candidates,target-candidates[i],i);
            temp.pop_back();
        }
    }
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        dfs(candidates,target,0);
        return res;
    }
    
};

括号生成

class Solution {
public:
    vector<string> res;
    vector<string> generateParenthesis(int n) {
        dfs(n,n,"");
        return res;
    }
    void dfs(int l, int j,string ans){
        if(l==0&&j==0) res.push_back(ans);
        if(l>0)dfs(l-1,j,ans+"(");
        if(j>l)dfs(l,j-1,ans+")");
    }
};

单词搜索

class Solution {
public:
    vector<vector<bool>> st;
    int dx[4] = {0,1,0,-1};
    int dy[4] = {-1,0,1,0};
    int n;
    int m;
    bool dfs(int x,int y,string word,vector<vector<char>>& board){
        if(word.size() == 0){
            return true;
        }
        for(int i = 0; i < 4; ++i){
            int nx = x + dx[i];
            int ny = y + dy[i];
            if(nx>=0 && nx < n && ny >=0 && ny < m && st[nx][ny] == false && board[nx][ny] == word[0]){
                st[nx][ny] = true;
                if(dfs(nx,ny,word.substr(1),board)){
                    return true;
                }
                st[nx][ny] = false;
            }
        }
        return false;
    }
    bool exist(vector<vector<char>>& board, string word) {
        n = board.size();
        m = board[0].size();
        st = vector<vector<bool>> (n,vector<bool>(m));
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m;j++){
                if(board[i][j] == word[0]){
                    st[i][j] = true;
                    if(dfs(i,j,word.substr(1),board)){
                        return true;
                    }
                    st[i][j] = false;
                }
            }
        }
        return false;
    }
};

分割回文串

class Solution {
public:
    bool isPalindrome(string &s, int left, int right) {
        while (left < right)
            if (s[left++] != s[right--])
                return false;
        return true;
    }
    vector<vector<string>> partition(string s) {
        vector<vector<string>> ans;
        vector<string> path;
        int n = s.length();
        // 前 后 保证不重复
        function<void(int, int)> dfs = [&](int i, int start) {
            if (i == n) {
                ans.emplace_back(path);
                return;
            }
            if(i < n-1){
                dfs(i+1,start);
            }
            if(isPalindrome(s,start,i)){
                path.push_back(s.substr(start,i-start+1));
                dfs(i+1,i+1);
                path.pop_back();
            }
        };
        dfs(0, 0);
        return ans;
    }
};

N皇后

class Solution {
public:
    int m;
    vector<vector<string>> res;
    vector<string> g;
    bool col[12],dg[24],udg[24];
    vector<vector<string>> solveNQueens(int n) {
        m = n;
        for(int i = 0; i < n; i++){
            g.push_back("");
            for(int j = 0; j < n; ++j){
                g[i]+='.';
            }
        }
        dfs(0);
        return res;
    }
    void dfs(int u){
        if(u == m){
            res.push_back(g);
            return;
        }
        for(int y = 0; y < m; ++y){
            if(col[y]==false&&dg[y-u+m]==false&&udg[y+u]==false){
                col[y] = dg[y-u+m] = udg[y+u] = true;
                g[u][y] = 'Q';
                dfs(u+1);
                g[u][y] = '.';
                col[y] = dg[y-u+m] = udg[y+u] = false;
            }
        }

    }
};

二分查找

搜索插入位置

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        int l = 0, r = nums.size()-1;
        if(nums[r] < target) return r+1;
        while(l<r){
            int mid = l + r  >> 1;
            if(nums[mid] >= target) r = mid;
            else l = mid + 1; 
        }
        return l;
    }
};

搜索二维矩阵

class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        int row = matrix.size();
        int col = matrix[0].size();
        int l = 0, r = row * col - 1;
        while(l < r){
            int mid = (l + r) >> 1;
            int x = mid / col;
            int y = mid - x * col;
            if(matrix[x][y] >= target){
                r = mid;
            }else l = mid + 1;
        }
        int x = l / col;
        int y = l - x * col;
        if(matrix[x][y] != target)return false;
        return true;
    }
};

## 在排序数组中查找元素的第一个和最后一个位置 ```cpp class Solution { public: vector searchRange(vector& nums, int target) { int l = 0, r = nums.size()-1; while(l

};

<a name="V301q"></a>
# 栈
<a name="YqnyU"></a>
## 有效的括号
```cpp
class Solution {
public:
    bool isValid(string s) {
        stack<char> stk;
        for(int i = 0; i < s.size(); ++i){
            char temp = s[i];
            if(temp ==')'){
                if(stk.size()==0 || stk.top() != '('){
                    return false;
                }
                stk.pop();
            }else if(temp =='}'){
                if(stk.size()==0 || stk.top() != '{'){
                    return false;
                }
                stk.pop();
            }else if(temp ==']'){
                if(stk.size()==0 || stk.top() != '['){
                    return false;
                }
                stk.pop();
            }else{
                stk.push(temp);
            }
        }
        if(stk.size()) return false;
        return true;
    }
};

字符串解码

class Solution {
public:
    string decodeString(string s) {
      stack<pair<int,string>> st;
      string res = "";
      int num = 0;
      for(int i = 0; i < s.size();++i){
        if(s[i]>='0' && s[i]<='9') {
          num = num*10 +  s[i] - '0';
        }else if(s[i] == '['){
          st.push(make_pair(num,res));
          num = 0;
          res = "";
        }else if(s[i] == ']'){
          int num = st.top().first;
          //取出之前的
          string pre = st.top().second;
          string cur;
          //取出里面的
          for(int i = 0; i < num;++i){
            cur += res;
          }
          //更新现在的
          res = pre + cur;
          st.pop();
        }else{
          res += s[i];
        }
      }
      return res;
    }
};

最小栈

class MinStack {
public:
    class Node{
    public:
        int val;
        int minval;
        Node* next;
        Node (int val,int min){
            this->val = val;
            this->minval = min;
            this->next = nullptr;
        }
        Node (int val,int min, Node* next){
            this->val = val;
            this->minval = min;
            this->next = next;
        }
    };
    Node* head;
    MinStack() {
       head = nullptr;
    }
    
    void push(int val)  {
        if(head == nullptr){
            head = new Node(val,val);
        }else head = new Node(val,min(val,head->minval),head);
    }
    
    void pop() {
        if (head) {
            Node* temp = head;
            head = head->next;
            delete temp;
        }
    }
    
    int top() {
        return head->val;
    }
    
    int getMin() {
        return head->minval;
    }
};

每日温度

class Solution {
public:
    int stk[100010],tt = -1;
    vector<int> dailyTemperatures(vector<int>& temperatures) {
        int n = temperatures.size();
        vector<int> ans(n,0);
        for(int i = 0; i < n; ++i){
            while(tt!=-1 && temperatures[stk[tt]] < temperatures[i]){
                int len = i - stk[tt];
                ans[stk[tt--]] = len;
            }
            stk[++tt] = i;
        }
        return ans;
    }
};

柱形图中最大的矩形

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        int ans = 0;
        vector<int> st;

        heights.insert(heights.begin(),0);
        heights.push_back(0);

        for(int i = 0; i < heights.size(); ++ i){
            while(!st.empty() && heights[st.back()] > heights[i]){
                int cur = st.back();
                st.pop_back();
                int left = st.back()+1; //剩下来的左边
                int right = i - 1; //当前插入的右边
                ans = max(ans,(right - left + 1) * heights[cur]);
            }
            st.push_back(i);
        }
        return ans;

    }
};
#include<iostream>
#include<algorithm>
#include<cstring>

using namespace std;
const int N = 100010;
int st[N];
int h[N];

int main(){
    int n;
    while(cin>>n, n!=0){
        long long ans = 0,tt = -1;
        memset(st, 0, sizeof st);
        memset(h,0,sizeof h);
        for(int i = 1; i <= n; ++i){
            scanf("%d",&h[i]);
        }
        n++;
        for(int i = 0; i <= n; i++){
            while(tt!=-1 && h[st[tt]] > h[i]){
                int cur = st[tt];
                int left = st[--tt] + 1;
                int right = i - 1;
                ans = max(ans,(long long)h[cur] * (right - left + 1));
            }
            st[++tt] = i;
        }
        cout<<ans<<endl;
        
    }
    return 0;
}

接雨水

剔除一个往左灌水 最后如果有挡板 往右灌水

#include<iostream>
#include<algorithm>
using namespace std;
const int N = 100010;
int st[N];
int h[N];
int n;

int main(){
    scanf("%d",&n);
    int res = 0, tt = -1;
    for(int i = 0; i < n; i++){
        scanf("%d",&h[i]);
    }
    for(int i = 0; i < n; i++){
        int last = 0;
        while(tt!=-1 && h[st[tt]] < h[i]){
            res += (h[st[tt]] - last) * (i - 1 - st[tt]);
            last = h[st[tt--]];
        }
        if(tt!=-1){
            res += (h[i] - last)*(i-1-st[tt]);
        }
        st[++tt] = i;
    }
    cout<<res<<endl;
    return 0;
}

数组中的第K个最大元素

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        for(int i = nums.size()/2; i >=0; --i){
            down(i,nums);
        }
        for(int i = 0; i < k-1; i++){
            nums[0] = nums[nums.size()-1];
            nums.pop_back();
            down(0,nums);
    
        }
        return nums[0];
    }
    void down(int u,vector<int>& nums){
        int t = u;
        if (u * 2 + 1 < nums.size() && nums[u * 2 + 1] > nums[t]) t = u * 2 + 1;
        if (u * 2 + 2 < nums.size() && nums[u * 2 + 2] > nums[t]) t = u * 2 + 2;
        if (u != t)
        {
            swap(nums[u], nums[t]);
            down(t,nums);
        }
    }
};

前 K 个高频元素

class Solution {
public:
    struct cmp{
        bool operator()(pair<int,int>a, pair<int,int>b){
            return a.second < b.second;
        }
    };


    vector<int> topKFrequent(vector<int>& nums, int k) {
        unordered_map<int, int> occurrences;
        for (auto& v : nums) {
            occurrences[v]++;
        }


        // pair 的第一个元素代表数组的值,第二个元素代表了该值出现的次数
        priority_queue<pair<int, int>, vector<pair<int, int>>, cmp> q;
        for (auto& [num, count] : occurrences) {
            q.emplace(num, count);
        }
        vector<int> ret;
        while (k--) {
            ret.emplace_back(q.top().first);
            q.pop();
        }
        return ret;
    }
};

数据流的中位数

class MedianFinder {
public:
    priority_queue<int, vector<int>, less<int>> queMax;
    priority_queue<int, vector<int>, greater<int>> queMin;


    MedianFinder() {}


    void addNum(int num) {
        if(queMax.empty() || num < queMax.top()){
            queMax.emplace(num);
            if(queMax.size() > queMin.size()+1){
                queMin.emplace(queMax.top());
                queMax.pop();
            }
        }else{
            queMin.emplace(num);
            if(queMin.size() > queMax.size()){
                queMax.emplace(queMin.top());
                queMin.pop();
            }
        }
    }


    double findMedian() {
        if ((queMin.size()  +  queMax.size() )& 1) {
            return queMax.top();
        }
        return (queMin.top() + queMax.top()) / 2.0;
    }
};

贪心

买卖股票的最佳时机

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

跳跃游戏

class Solution {
public:
    bool canJump(vector<int>& nums) {
        int ed = 0;
        for(int i = 0; i < nums.size() && i <= ed; ++i){
            ed = max(ed,i+nums[i]);
            if(ed >= nums.size()-1) return true;
        }
        return false;
    }
};

跳跃游戏2

class Solution {
public:
    int jump(vector<int>& nums) {
        int n = nums.size();
        int ans[nums.size()+1];
        memset(ans,0x3f,sizeof ans);
        ans[0] = 0;
        for(int i = 0; i < n; ++i){
            for(int j = 1; j <= nums[i] && i+ j < n; ++j){
                ans[i+j] = min(ans[i+j],ans[i] + 1);
            }
        }
        return ans[n-1];
    }
};

划分字母区间

动态规划

爬楼梯

class Solution {
public:
    int f[45];
    int climbStairs(int n) {
        if (n <= 1) return n; 
        vector<int> dp(n + 1);
        dp[1] = 1;
        dp[2] = 2;
        for (int i = 3; i <= n; i++) { 
            dp[i] = dp[i - 1] + dp[i - 2];
        }
        return dp[n];
    }
};

杨辉三角

class Solution {
public:
    vector<vector<int>> generate(int numRows) {
        vector<vector<int>> res;
        res.push_back({1});
        vector<int> temp;
        for(int i = 1; i < numRows; i++){
            for(int j = 0; j <= i; j++){
                if(j == 0 || j == i){
                    temp.push_back(1);
                }else{
                    temp.push_back(res[i-1][j] + res[i-1][j-1]);
                }
            }
            res.push_back(temp);
            temp.clear();
        }
        return res;
    }
};

打家劫舍

class Solution {
public:
    int rob(vector<int>& nums) {
        int res = 0;
        int dp[nums.size()];
        if(nums.size() == 1){
            return nums[0];
        }
        dp[0] = nums[0];
        dp[1] = max(nums[0],nums[1]);
        for(int i = 2; i < nums.size(); i++){
            dp[i] = max(dp[i-2]+nums[i],dp[i-1]);
        }
        return dp[nums.size()-1];
    }
};

完全平方数

class Solution {
public:
    int numSquares(int n) {
    int f[n+2];
    memset(f,0x3f,sizeof f);
    f[0] = 0;
    for(int i = 1; i * i<= n; i++){
        for(int j = i*i; j <= n; j++){
            f[j] = min(f[j],f[j-i*i]+1); 
        }
    }
    return f[n];
    }
};

零钱兑换

class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        int f[amount+2];
        memset(f,0x3f,sizeof f);
        sort(coins.begin(),coins.end());
        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] == 0x3f3f3f3f){
            return -1;
        }
        return f[amount];
    }
};

单词拆分

class Solution {
public:
    bool wordBreak(string s, vector<string>& wordDict) {
        auto wordSet = unordered_set <string> ();
        for (auto word: wordDict) {
            wordSet.insert(word);
        }
        int n = s.length();
        vector<bool> dp(n+1,0);
        for(int i = 0; i < n; i++){
            for(int j = i; j < n; j++){
                if(dp[j]!=true && (i==0 || dp[i-1] == true) && wordSet.find(s.substr(i,j-i+1))!=wordSet.end()){
                    dp[j] = true;
                }
            }
        }
        return dp[n-1];
    }
};

最长递增子序列

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

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        int n = nums.size();
        int q[n+2];
        int len =  0;
        for(int i = 0; i < n; i++){
            int l = 0,r =len;
            while(l<r){
                int mid = l + r + 1>> 1;
                if(q[mid] < nums[i]){
                    l = mid;
                }else r = mid -1;
            }
            len = max(len,r+1);
            q[r+1] = nums[i];
        }
        return len;
        
    }
};

乘积最大子数组

class Solution {
public:
    int maxProduct(vector<int>& nums) {
        int len = nums.size();
        int result = nums[0];
        int maxcurr = result;
        int mincurr = result;
        for(int i = 1; i < len; i++){
            int last = maxcurr;
            maxcurr = max(nums[i],max(nums[i]*maxcurr,nums[i]*mincurr));
            mincurr = min(nums[i],min(nums[i]*last,nums[i]*mincurr));
            result = max(result,maxcurr);
        }
        return result;
    }
};

分割等和子集

class Solution {
public:
    bool canPartition(vector<int>& nums) {
        int res = 0;
        for(int i = 0; i < nums.size(); i++){
            res += nums[i];
        }
        if(res%2 == 1){
            return false;
        }
        bool f[res/2+2];
        memset(f,0,sizeof f);
        f[0] = 1;
        for(int i = 0; i < nums.size(); i++){
            for(int j = res/2; j >= nums[i]; j--){
                f[j] = max(f[j],f[j-nums[i]]);
            }
        }
        return f[res/2];
    }
};

最长有效括号

class Solution {
public:
    int longestValidParentheses(string s) {
        int n = s.size();
        vector<int> f(n+1);
        int start = 0;
        int res = 0;
        for(int i = 0; i < n; i++){
            if(s[i] == '('){
                start = 1;
                for(int j = i + 1; j < n; ++j){
                    if(s[j] == '('){
                        start++;
                    }else{
                        start--;
                        if(start == 0){
                            res = max(res,j-i+1);
                        }else if(start < 0){
                            i = j;
                            break;
                        }
                    }
                }
            }
        }
        return res;
    }
};
class Solution {
public:
    int longestValidParentheses(string s)
    {
        stack<int> stk;
        stk.push(-1);
        int maxLen = 0;
        for (int i = 0; i < s.size(); i++) {
            if (stk.size() != 1 && s[stk.top()] == '(' && s[i] == ')') {
                stk.pop();
                // 最初的位置
                maxLen = max(maxLen, i - stk.top());
            } else {
                stk.push(i);
            }
        }
        return maxLen;
    }
};

多维动态规划

不同路径

class Solution {
public:
    int uniquePaths(int m, int n) {
        vector<vector<int>> f(m,vector<int>(n));
        for(int i =0; i < m; i++)f[i][0] = 1;
        for(int j =0; j < n; j++) f[0][j] = 1;
        for(int i = 1; i < m; i++){
            for(int j = 1; j < n; j++){
                f[i][j] = f[i-1][j] + f[i][j-1];
            }
        }
        return f[m-1][n-1];
    }
};

最小路径和

class Solution {
public:
    int minPathSum(vector<vector<int>>& grid) {
        int n = grid.size();
        int m = grid[0].size();
        vector<vector<int>> f(n,vector<int>(m));
        // memset(f,0x3f,sizeof f);
        f[0][0] = grid[0][0];
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m;++j){
                if(i==0&&j==0)continue;
                if(i == 0){
                    f[i][j] = f[i][j-1] + grid[i][j];
                }else if(j == 0){
                    f[i][j] = f[i-1][j] + grid[i][j];
                }else{
                    f[i][j] = min(f[i-1][j],f[i][j-1]) + grid[i][j];
                }
            }
        }
        return f[n-1][m-1];
    }
};

最长公共子序列

class Solution {
public:
    int longestCommonSubsequence(string text1, string text2) {
        int a = text1.size();
        int b = text2.size();
        vector<vector<int>> dp(text1.size() + 1, vector<int>(text2.size() + 1, 0));
        int ans = 0;
        dp[0][0] = 0;
        for(int i = 1; i <= a; i++){
            for(int j = 1; j <= b; j++){
                dp[i][j] = max(dp[i][j-1],dp[i-1][j]);
                if(text1[i-1] == text2[j-1]) dp[i][j] = max(dp[i][j],dp[i-1][j-1]+1);
                ans = max(ans,dp[i][j]);
            }
        }
        return ans;
    }
};

最长回文子串

class Solution {
public:
    string longestPalindrome(string s) {
        int n = s.size();
        bool f[n+1][n+1];
        memset(f,0,sizeof f);
        int maxlen = 1;
        string res = s.substr(0,1);
        for(int i = 0; i < n; i++){
            f[i][i] = true;
        }
        for(int len = 2; len <= n; len++){
            for(int j = 0; j + len - 1 < n; j++){
                int l = j, r = j + len -1;
                if(len == 2 && s[l] == s[r]){
                    f[l][r] = true;
                    if(len > maxlen){
                        maxlen = len;
                        res = s.substr(l,len);
                    }
                }else if(s[l] == s[r] &&(l+1<n) && f[l+1][r-1]){
                    f[l][r] = true;
                    if(len > maxlen){
                        maxlen = len;
                        res = s.substr(l,len);
                    }
                }
            }
        }
        return res;
    }
};

编辑距离

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

技巧

只出现一次的数字

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int res = 0;
        for(int i = 0; i < nums.size(); ++i){
            res ^= nums[i];
        }
        return res;
    }
};

多数元素

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        int res = nums[0];
        int len = 1;
        for(int i = 1; i < nums.size(); ++i){
            if(nums[i] == res){
                len++;
            }else{
                len--;
                if(len == 0){
                    res = nums[++i];
                    len = 1;
                }
            }
        }
        return res;
    }
};

颜色分类

class Solution {
public:
    void sortColors(vector<int>& nums) {
        int l = 0, r = nums.size()-1;
        for(int i = 0; i<=r;){//注意等号
            if(nums[i]==0){
                swap(nums[i],nums[l++]);
                i++;
            }else if(nums[i] == 2){
                swap(nums[i],nums[r--]);
            }else{
                i++;
            }
        }
    }
};

下一个排列

class Solution {
public:
    void nextPermutation(vector<int>& nums) {
        int i = nums.size()-2;
        while(i >= 0 && nums[i] >= nums[i+1]){
            i--;
        }
        if(i>=0){
            int j = nums.size()-1;
            while(j>=0 && nums[i] >= nums[j]){
                j--;
            }
            swap(nums[i],nums[j]);
        }
        reverse(nums.begin()+i+1,nums.end());
    }
};

寻找重复数

class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        
        int fast = 0, slow = 0;
        while(true){
            fast = nums[nums[fast]];
            slow = nums[slow];
            if(fast == slow)
                break;
        }
        int finder = 0;
        while(true){
            finder = nums[finder];
            slow = nums[slow];
            if(slow == finder)
                break;        
        }
        return slow;
    }
};
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值