leetcode中的codeTop前频次>50题以及部分评论区附加题。非会员题

提供一个简单刷题的飞书Excel模板
https://kpnhh4zsm6.feishu.cn/sheets/N4tlsx05PhrJaLtcJEmccfnfn9d

尽量写的简洁好背。
“想要背的快,除了多敲,优化逻辑,让思维固化没有其他办法”。提供一份简介的代码。
1.能不嵌套自增语句就不嵌套
2.链表涉及迭代一定要用dummy,递归看情况

3. 无重复字符的最长子串#

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        unordered_map<char,int>m;//可以换成字符数组
        int res=0;
        for(int r=0,l=0;r<s.size();r++){
            m[s[r]]++;
            while(m[s[r]]>1) m[s[l++]]--;
            res=max(res,r-l+1); 
        }
        return res;
    }
};

395. 至少有 K 个重复字符的最长子串#

class Solution {
public:
    int k;
    unordered_map<char,int>m;
    void add(char c,int &x,int &y){
        if(!m[c]) x++;//出现的不同的字符数
        m[c]++;
        if(m[c]==k) y++;//满足条件的字符数
    }
    void remove(char c,int &x,int &y){
        if(m[c]==k) y--;
        m[c]--;
        if(m[c]==0) x--;
    }
    int longestSubstring(string s, int _k) {
        k=_k;
        int res=0;
        for(int cnt=1;cnt<=26;cnt++){//用双指针先保证单调 现在字母出现次数k,出现不同字母数。我们固定不同字母数,超过就找下一段。(之前题相当于固定出现次数)
            m.clear();
            for(int l=0,r=0,diffchar=0,fix=0;r<s.length();r++){
                add(s[r],diffchar,fix);
                while(diffchar>cnt) remove(s[l++],diffchar,fix);

                if(diffchar==fix) res=max(res,r-l+1);//满足条件
            }
        }
        return res;
    }
};

206. 反转链表#

都要先保存next。
//迭代  while(head),return pre
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* pre=nullptr;
        while(head){
            auto next=head->next;
            head->next=pre;
            pre=head;
            head=next;
        }
        return pre;
    }
};

//递归 递归next,return newhead
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if(!head||!head->next) return head;
        auto next = head->next;
        auto newhead = reverseList(head->next);
        next->next=head;
        head->next=nullptr;
        return newhead;
    }
};

146. LRU 缓存#

struct node{
    int key;
    int val;
    node* pre;
    node* next;

    node():key(0),val(0),pre(nullptr),next(nullptr){};
};
class LRUCache {
public:
    map<int,node*>m;//哈希表快速找
    int size=0,capacity=0;//容量和当前容量
    node* head=new node();
    node* tail=new node();
    LRUCache(int _capacity) {
        capacity=_capacity;
        head->next=tail;
        tail->pre=head;
    }
    
    int get(int key) {
        if(!m.count(key)) return -1;
        else {
            auto node=m[key];
            movetohead(node);
            return node->val;
        }
    }
    
    void put(int key, int value) {
        if(m.count(key)){
            auto node=m[key];
            node->val=value;
            movetohead(node);
        }else{
            auto newnode=new node();
            newnode->val=value;
            newnode->key=key;
            addtohead(newnode);
            m[key]=newnode;
            ++size;
            if(size>capacity){
                auto p=tail->pre;
                deletenode(p);
                --size;
                m.erase(p->key);
                delete p;
            }
        }
    }

    void deletenode(node* node){
        node->pre->next=node->next;
        node->next->pre=node->pre;
        
    }

    void addtohead(node* node){
        node->next=head->next;
        node->pre=head;
        head->next->pre=node;
        head->next=node;
    }
    void movetohead(node *node){
        deletenode(node);
        addtohead(node);
    }
    


};

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

215. 数组中的第K个最大元素#

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        int n=nums.size();
        return find(nums,0,n-1,n-k);//注意最大
    }
    int find(vector<int>&nums,int l,int r,int k){
        if(l==r) return nums[l];
        int i=l-1,j=r+1,x=nums[l];
        while(i<j){
            while(nums[++i]<x);
            while(nums[--j]>x);
            if(i<j) swap(nums[i],nums[j]);
        }

        if(k<=j) return find(nums,l,j,k);
        else return find(nums,j+1,r,k);//此做法不需要改变K的值
    }
};

25. K 个一组翻转链表#

class Solution {
public:
    ListNode* reverseKGroup(ListNode* head, int k) {
        if(head==nullptr||head->next==nullptr) return head;
        auto tail = head;
        for (int i = 0; i < k; i++) {//一共走了k步所以k是尽头
            //剩余数量小于k的话,则不需要反转。
            if (tail == nullptr) {
                return head;//发现居然遍历到尾节点 说明不够 直接返回
            }
            tail = tail->next;
        }
        auto newhead= reverse(head,tail);//翻转这k个元素获得翻转后新的头节点  3,4的话 这个值就是4
        head->next =reverseKGroup(tail,k);//递归处理之后的 原节点就是尾巴节点 和下一个的连接 这个4 

        return newhead;
    }

    ListNode* reverse(ListNode* head,ListNode*tail){
        ListNode* pre =NULL;
        while(head!=tail){//左开右闭
            auto next = head->next;
            head->next=pre;//
            pre=head;
            head=next;
        }
        
        return pre;
    }


};

K 个一组翻转链表 迭代#

class Solution {
public:
    ListNode* reverseKGroup(ListNode* head, int k) {
        if(!head||!head->next) return head;
        auto dummy=new ListNode();//dummy不动 pre动 
        dummy->next=head;
        auto pre=dummy;
        while(head){
            auto tail = pre;
            for(int i=0;i<k;i++){
                tail=tail->next;
                if(!tail){
                    return dummy->next;//与递归不一致 这里先走 再判空
                }
            }
            auto nex=tail->next;
            auto newhead=tail;
            auto newtail=head;
            
            reverse(head,tail);

            pre->next=newhead;//还原为链表
            newtail->next=nex;

            pre=newtail;//跳转
            head=nex;
        }

        return dummy->next;
    }
    ListNode* reverse(ListNode* head,ListNode *tail){//左闭右闭的区间
        ListNode* pre=nullptr;
        while(pre!=tail){
            auto next=head->next;
            head->next=pre;
            pre=head;
            head=next;
        }
        
        return pre;
    }
};

三数之和#

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>>res;
        sort(nums.begin(),nums.end());
        int n=nums.size();
        for(int a=0;a<n-2;a++){//最左端+最右端 往中间走
            if(a>0&&nums[a]==nums[a-1]) continue;//重新跳过流程
            int b=a+1,c=n-1;
            while(b<c){
                if(nums[a]+nums[b]+nums[c]>0) c--;
                else if(nums[a]+nums[b]+nums[c]<0) b++;
                else{
                    res.push_back({nums[a],nums[b],nums[c]});
                    
                    while(b<c&&nums[b]==nums[b+1]) b++;
                    while(b<c&&nums[c]==nums[c-1]) c--;
                    b++;c--;//去重

                }
            }
        }

        return res;
    }
};

16. 最接近的三数之和#

class Solution {
public:
    int threeSumClosest(vector<int>& nums, int target) {
        sort(nums.begin(),nums.end());
        int n=nums.size();
        int diff = INT_MAX, res = 0;
        for(int a=0;a<n-2;a++){
            if(a>0&&nums[a]==nums[a-1]) continue;//重新跳过流程
            int b=a+1,c=n-1;
            while(b<c){
                if(nums[a]+nums[b]+nums[c]>target){
                    if (abs(nums[a] + nums[b] + nums[c] - target) <diff) {
                        res = nums[a] + nums[b] + nums[c];
                        diff = abs(nums[a] + nums[b] + nums[c] - target);
                    }
                    c--;
                } 
                else if(nums[a]+nums[b]+nums[c]<target){
                    if (abs(nums[a] + nums[b] + nums[c] - target) <diff) {
                        res = nums[a] + nums[b] + nums[c];
                        diff = abs(nums[a] + nums[b] + nums[c] - target);
                    }
                    
                    b++;
                }
                else{
                    if (abs(nums[a] + nums[b] + nums[c] - target) <diff) {
                        res = nums[a] + nums[b] + nums[c];
                        diff = abs(nums[a] + nums[b] + nums[c] - target);
                    }
                    
                    while(b<c&&nums[b]==nums[b+1]) b++;
                    while(b<c&&nums[c]==nums[c-1]) c--;
                    b++;c--;

                }
            }
        }

        return res;
    }
};

53. 最大子数组和#

三种做法
1.分治线段树。题目所谓精妙解法
2.on前缀和-dpmin最小值。但是不方便拓展
3.先记录last=当前新加的数+max(前面一段最大值,0),
最大值就是之前最大值和当前这一段last。能求最大的数组是谁

//分治
class Solution {
public:
    struct Node{
        int sum,s,ls,rs;//总和,最大子数组和,最大前缀,最大后缀
    };

    Node build(vector<int>&nums, int l, int r){//表示对l,r范围内建树
        if(l == r) {
            return {nums[l], nums[l], nums[l], nums[l]};
        }
        int mid = l + r >> 1;
        auto L = build(nums,l,mid), R =build(nums,mid+1,r);
        //合并左右信息
        Node res;
        res.sum = L.sum + R.sum;
        res.s = max(max(L.s,R.s),L.rs+R.ls);
        res.ls = max(L.ls, L.sum+R.ls);
        res.rs = max(R.rs, R.sum+L.rs);
        return res; 
    }

    int maxSubArray(vector<int>& nums) {
        
        auto t = build(nums,0,nums.size()-1);
        return t.s;
    }
};


//dp
class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        //fi表示所有以nums_i结尾的区间中 最大和是多少
        int res=INT_MIN;
        for(int i=0,last=0;i<nums.size();i++){
            last = nums[i] + max(last,0);
            res = max(res,last);
        }
        return res;
    }
};

//求最大子数组是什么版本
class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int maxv=INT_MIN;
        vector<int>res,lastve;
        for(int i=0,last=0;i<nums.size();i++){
            vector<int>v;
            bool f1=false,f2=false;
            if(last>=0) f1=true;//判断上一段是否大于0 说明肯定使用上一段
            last = nums[i] + max(last,0);//last负责新开的一段是否连带之前一段
            
            if(maxv<last) f2=true;//说明当前段比较大 更改答案
            maxv = max(maxv,last);//maxv负责让当前一段与过去的最大值做比较
            
            if(f1) {
                lastve.push_back(nums[i]);
            }else if(!f1){
                v.push_back(nums[i]);
                lastve=v;
            }
            if(f2){
                res=lastve;
            }
        }
        // for(auto x:res) cout<<x<<" ";
        return maxv;
    }
};

912. 排序数组#

快排

class Solution {
public:
    vector<int> sortArray(vector<int>& nums) {
        qsort(nums,0,nums.size()-1);
    
        return nums;
    }
    void qsort(vector<int>& nums,int l,int r){
        if(l>=r) return;
        int i=l-1,j=r+1,x=nums[l+r>>1];
        while(i<j){
            while(nums[++i]<x);
            while(nums[--j]>x);
            if(i<j) swap(nums[i],nums[j]);
        }
        qsort(nums,l,j);
        qsort(nums,j+1,r);
    }
};

归并排序#

class Solution {
public:
    vector<int> sortArray(vector<int>& nums) {
        msort(nums,0,nums.size()-1);
    
        return nums;
    }
    void msort(vector<int>& nums,int l,int r){
        if(l>=r) return;
        int mid=l+r>>1;
        
        msort(nums,l,mid);
        msort(nums,mid+1,r);
        int temp[nums.size()],i=l,j=mid+1,k=0;
        while(i<=mid&&j<=r){
            if(nums[i]<=nums[j]) temp[k++]=nums[i++];
            else temp[k++]=nums[j++];
        }

        while(i<=mid) temp[k++]=nums[i++];
        while(j<=r) temp[k++]=nums[j++];

        for(int i=l,j=0;i<=r;i++,j++) nums[i]=temp[j];
    }
};

堆排序#

class Solution {
public:
    vector<int>h;
    int cnt ;
    vector<int> sortArray(vector<int>& _nums) {
        h=_nums;
        cnt=_nums.size()-1;
        for (int i = cnt / 2; i>=0; i -- ){
            down(i);//从右下到左上 这里i>=0所以cnt=0        
        } 
        for(int i=cnt;i>=1;i--)
        {
            swap(h[0],h[i]);
            cnt--;
            down(0);
        }
        reverse(h.begin(),h.end());
        return h;
    }

    void down(int u)
    {
        int t = u;//最小节点 
        if (u * 2 +1 <= cnt && h[u * 2+1] < h[t]) t = u * 2+1;//左节点 这里如果起始点从0开始就u<<1+1 从1开始就u<<1
        if (u * 2 + 2 <= cnt && h[u * 2 + 2] < h[t]) t = u * 2 + 2;//右节点
        if (u != t)//待调整点不是最小的
        {
            swap(h[u], h[t]);//把小的节点往上挪
            down(t);
        }
    }

};

21. 合并两个有序链表#

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
        //如果要求去重 while跳到最后一个
        if(!list1) return list2;
        if(!list2) return list1;
        if(list1->val<list2->val) {
            list1->next=mergeTwoLists(list1->next,list2);
            return list1;
        }
        else {//如果要求去重 再加if判断让递归(next,next)
            list2->next=mergeTwoLists(list1,list2->next);
            return list2;
        }
    }
};

迭代

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
        if(!list1) return list2;
        if(!list2) return list1;
        
        ListNode* dummy = new ListNode();
        ListNode* head = dummy;
        while(list1&&list2){
            //如果去重 这里对两条链while
            if(list1->val<list2->val){
                head->next=list1;
                list1=list1->next;  
            } 
            else{
                head->next=list2;
                list2=list2->next;
            } 
            head=head->next;
            // cout<<head->val<<" ";
        }
        if(!list1) head->next=list2;
        if(!list2) head->next=list1;
        return dummy->next;
    }
};

5. 最长回文子串#

lc647回文子串、lc5最长回文子串、lc516最长回文子序列

class Solution {
public:
    string longestPalindrome(string s) {
        int n=s.size();
        vector<vector<int>>f(n,vector<int>(n,0));
        int p=-1,res=-1;
        for(int len=1;len<=n;++len){
            for(int i=0;i+len-1<n;i++){
                if(len==1){
                    f[i][i]=1;
                    p=i;
                    res=len;
                    continue;
                }
                
                int j=i+len-1;
                if(s[i]==s[j]){
                    if(len==2)  f[i][j]=1; 
                    else  f[i][j]=f[i+1][j-1];

                    if(f[i][j]){
                        p=i;
                        res=len;
                    }
                } 
            }
        }
        
        return s.substr(p,res);
    }
};

中心拓展法

class Solution {
public:
    string longestPalindrome(string s) {
        // maxL:记录最长回文串长度
        // maxl:记录最长回文串的开头位置
        int maxLen = 0, maxl = 0;
        // 枚举每个数
        for( int i = 0; i < s.size(); ++i ) {
            // 1.以这个数和前一个数之间的空隙 作为对称中点
            int l = i-1, r = i ;
            // 左右寻找该回文列的尽头,注意边界
            for( ; l >= 0 && r < s.size() && s[l] == s[r]; --l, ++r);
            if( maxLen < r-l-1 ) {
                maxl = l+1;
                maxLen = r-l-1;
            }

            // 2.以这个数 作为对称中点
            l = i-1, r = i+1;
            // 左右寻找该回文列的尽头,注意边界
            for( ; l >= 0 && r < s.size() && s[l] == s[r]; --l, ++r);
            if( maxLen < r-l-1 ) {
                maxl = l+1;
                maxLen = r-l-1;
            }
        }
        return s.substr(maxl, maxLen);
    }
};

1. 两数之和#

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int,int>m;//哈希表是O(N) 但是不能让她值为0 
        for(int i=0,j=0;i<nums.size();i++){
            int r=target-nums[i]; 
            if(m.count(r)) return {m[r],i};
            m[nums[i]]= i;
        }   
        
        return {};
    }
    
};

102. 二叉树的层序遍历#

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>>res;
        if(!root) return res;
        queue<TreeNode*>q;
        q.push(root);
        
        while(q.size()){
            vector<int>v;
            int n=q.size();
            for(int i=0;i<n;i++){
                TreeNode* t=q.front();
                // cout<<t->val;
                q.pop();
                v.push_back(t->val);
                if(t->left)
                q.push(t->left);
                if(t->right)
                q.push(t->right);
            }
            res.push_back(v);
        }
        return res;
    }
};
迭代方法
dfs(,level+1) 记录level信息即可

33. 搜索旋转排序数组#

33-查找旋转数组不重复;81-查找旋转数组可重复复;153-旋转数组最小值不重复;154旋转数字最小值重复

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int n = nums.size();
        int l = 0, r = n - 1;
        
        while(l < r){
            int mid = l + r + 1 >> 1;
            if(nums[mid] >= nums[0]){//找打最大的数nums0
                l = mid;
            }
            else r = mid - 1;
        }
        // cout<<l<<" "<<r;//l和r都会最终指向那个分割点前一个
        if(target >= nums[0]){//目标值比第一个值还要大 说明在左边这一段
            l = 0;
        }
        else{//说明在右边这一段
            l = l + 1;
            r = n - 1;
        }
        while(l < r){//二分
            int mid = l + r >> 1;
            if(nums[mid] >= target){
                r = mid;
            }
            else l = mid + 1;
        }
        return (nums[r] == target ? r : -1);
    }
};


200. 岛屿数量#

class Solution {
public:
    int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};

    int res=0;
    int n=0,m=0;
    int numIslands(vector<vector<char>>& grid) {
        n=grid.size(),m=grid[0].size();

        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){

                if(grid[i][j]=='1')
                {
                    bfs(i,j,grid);
                    res++;
                    grid[i][j]='0';
                }
            }

        }   
        return res;
    }
    void bfs(int x,int y,vector<vector<char>>& grid){
        queue<pair<int,int> >q;
        q.push({x,y});
        while(q.size()){
            auto t=q.front();
            q.pop();
            for(int i=0;i<4;i++){
                int a=t.first+dx[i],b=t.second+dy[i];

                if(a<0||a>=n||b<0||b>=m||grid[a][b]!='1') continue;

                grid[a][b]='0';
                q.push({a,b});
            }
        }
    }
};

121. 买卖股票的最佳时机 (一次交易)#

https://leetcode.cn/circle/discuss/qiAgHn/

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

122. 买卖股票的最佳时机 II (无限次交易,因为可以当天买入当天卖出,仍然贪心)#

int maxProfit(int* prices, int pricesSize){
    int total=0;
    for(int i=0;i+1<pricesSize;i++){
        if(prices[i]<prices[i+1]){
            total+=prices[i+1]-prices[i];
        }
    }
    return total;
}

20. 有效的括号#

class Solution {
public:
    bool isValid(string s) {
        stack<char>stk;
        for(auto &c:s){
            if(c=='('||c=='['||c=='{') stk.push(c);
            else{//小于等于2是因为有[]中间有别的字符,1不行。然后abs 防止小-大
                if(stk.size()&& abs(c-stk.top())<=2) stk.pop();
                else return false;
            }
        }
        return stk.empty();
    }
};

46. 全排列#

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

};

88. 合并两个有序数组(原地算法倒序遍历)#

class Solution {
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
        int i=m-1,j=n-1;
        vector<int>v;
        for(int k=m+n-1;k>=0;k--){
            if(i==-1) nums1[k]=nums2[j--];           
            else if(j==-1) nums1[k]=nums1[i--];
            else if(nums1[i]>nums2[j]){
                nums1[k]=nums1[i--];
            }else{
                nums1[k]=nums2[j--];   
            } 
        }
        
    }
};

141. 环形链表 (先跳再判断)#

ListNode *detectCycle(ListNode *head) {
        if(!head||!head->next) return NULL;
        ListNode* fast=head;
        ListNode* slow=head;
        while(fast){
            fast=fast->next;slow=slow->next;
            if(!fast) return NULL;

            fast=fast->next;
            if(!fast) return NULL;

            if(slow==fast) {//有环 可以直接return
                fast=head;//下面找入环点 fast重回开头
                while(slow!=fast){
                    slow=slow->next;
                    fast=fast->next;
                }
                return fast;
            }
        }
        return NULL;
        
    }

236. 二叉树的最近公共祖先#

class Solution {
public:
    int ans=0;
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        return dfs(root,p,q);
    }
    TreeNode* dfs(TreeNode* root,TreeNode* p,TreeNode* q){
        //如果找到了p或者q 那么就返回。找不到返回为空
        if(!root||root==p||root==q) return root;
        
        //left 和 right
        TreeNode* left=dfs(root->left,p,q);
        TreeNode* right=dfs(root->right,p,q);   
        if(!left&&!right) return NULL;
        if(!left) return right;
        if(!right) return left;
        //上面都通过了 说明剩下left&&right的情况
        return root;//只有当left 或者 right的值都不为空的时候 也就是p和q的时候 这个值就是对应的。否则说明不在这个子树里面
    }
};

92. 反转链表 II#

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int left, int right) {
        auto dummy=new ListNode();
        dummy->next=head;
        auto p=dummy;
        for(int i=0;i<left-1;i++){
            p=p->next;
        }
        auto q=p;

        for(int i=0;i<right-left+1;i++){
            q=q->next;
        }
        auto t=q->next;
        reverse(p->next,q->next);
        
        p->next->next=t;
        p->next=q;        
        return dummy->next;
    }
    void reverse(ListNode* head,ListNode *tail){
        ListNode* pre=nullptr;
        while(head!=tail){
            auto next=head->next;
            head->next=pre;
            pre=head;
            head=next;
        }
        return;
    }
};

23. 合并 K 个升序链表#

class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {

        if(lists.size()==0) return nullptr; 
        if(lists.size()==1) return lists[0]; 
        return merge(lists,0,lists.size()-1);;
    }
    ListNode* merge(vector<ListNode*>& lists,int l,int r){
        if(l==r) return lists[l];
        int mid =l+r>>1;
        auto left=merge(lists,l,mid);
        auto right=merge(lists,mid+1,r);

        return merge(left,right);
    }
    ListNode* merge(ListNode* l1,ListNode* l2){
        if(!l1) return l2;
        if(!l2) return l1;
        if(l1->val<l2->val){
            l1->next=merge(l1->next,l2);
            return l1;
        } else{
            l2->next=merge(l1,l2->next);
            return l2;
        }
        
    }
};

最长递增子序列#

//能求序列是谁的 onlog
class Solution {
public:
    int lengthOfLIS(vector<int>& arr) {
        if(arr.size() < 2) return arr.size();
        vector<int> dplen(arr.size(), 1);//(以i结尾的最长递增子序列长度)
        vector<int> st(1, arr[0]);//st[k]表示长度为k+1的递增长子序列的最后一个元素,并且是字典序最小的那个
        for(int i = 1; i < arr.size(); i++) {
            if(arr[i] > st.back()) { // in inc seq     
                st.push_back(arr[i]);
                dplen[i] = st.size();
            } else { // ai < maxEnd   
                int l=0,r=st.size()-1;
                while(l<r){
                    int mid = l+r>>1;
                    if(st[mid]>=arr[i]){
                        r=mid;
                    }
                    else{
                        l=mid+1;
                    }
                }
                //在栈中找到>=nums[i]的位置 也就是最左边的位置
                st[r] = arr[i];//idx是要插入的位置的下标
                dplen[i] = r + 1;//下标+1才是长度

            }
            
        }

        int len = st.size();
        vector<int> vres(len);
        
        for(int i = arr.size()-1; i >= 0; --i) {
            if(dplen[i] == len) {
                //vres求字典序最小的子序列。因为如果不是字典序更小的话,前面有一个i小于当前j,但是i<j在上面已经直接push了 不会出现长度一样的情况
                vres[len-1] = arr[i];
                --len;
            }
        }

        return vres.size();
    }
    
};

重排链表#

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    //找中间节点 + 反转链表 + 哑巴节点
    void reorderList(ListNode* head) {
        auto mid=findMid(head);
        auto newhead=mid->next;
        mid->next=nullptr;
        auto tail=reverse(newhead);
        merge(head,tail);
    }
    ListNode* findMid(ListNode* head){
        if(!head) return head;
        auto slow=head,fast=head;
        while(fast->next&&fast->next->next){
            slow=slow->next;
            fast=fast->next->next;
        }
        return slow;
    }
    ListNode* reverse(ListNode*head){
        ListNode* pre=nullptr;
        while(head){
            auto next=head->next;
            head->next=pre;
            pre=head;
            head=next;
        }
        return pre;
    }
    ListNode* merge(ListNode* a, ListNode* b){
        auto dummy=new ListNode(0);
        dummy->next=a;
        while(a&&b){
            auto na=a->next,nb=b->next;
            a->next=b;b->next=na;
            a=na;b=nb;
        }
        
        return dummy->next;
    }  
    
};

42.接雨水#

O1空间
class Solution {
public:
    int trap(vector<int>& height) {
        int n=height.size();
        int leftmax=0,rightmax=0;
        int left=0,right=height.size()-1;
        int ans=0;
        while(left<right){
            leftmax=max(leftmax,height[left]);
            rightmax=max(rightmax,height[right]);
            if(height[left]<height[right]){//left<right
                ans+=leftmax-height[left];
                ++left;
            }else{
                ans+=rightmax-height[right];
                --right;
            }
        }
        
        return ans;
    }
};

142. 环形链表 II#

证明:
相遇时 slow在环内的b位置 环内剩余c
B走:a+b
A走:a+b+n(b+c)
因为a是b的22*(a+b)=a+b+n(n+c)
得到
a=c+(n-1)(b+c)
也就是 也就是到环的位置,是fast重新走a,slow在这期间会把c走完走到环的起始点
/**
 * 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) {
        if(!head||!head->next) return NULL;
        auto fast=head,slow=head;
        while(fast){
            slow=slow->next;
            fast=fast->next;
            if(!fast)  return NULL;
            fast=fast->next;
            if(!fast)  return NULL;
            if(slow==fast){
                fast=head;
                while(fast!=slow){
                    fast=fast->next;
                    slow=slow->next;
                }
                return fast;
            }
        }
        return NULL;
    }
};

56. 合并区间#

class Solution {
public:
    vector<vector<int>> merge(vector<vector<int>>& a) {
        vector<vector<int>>res;
        if(a.empty()) return res;
        sort(a.begin(),a.end());

        int l=a[0][0],r=a[0][1];
        for(int i=1;i<a.size();i++){
            if(a[i][0] > r){
                res.push_back({l,r});
                l=a[i][0],r=a[i][1];
            }else{
                r= max(r,a[i][1]);
            }
        }
        res.push_back({l,r});
        return res;
    }
};

124. 二叉树中的最大路径和 (打印路径版)#

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
struct Pair {
    int sum;
    vector<int> path;
    Pair(int sum, const vector<int>& path) : sum(sum), path(path) {}
};
class Solution {
private:
    int ans = INT_MIN;
    vector<int> maxPath;

public:
    int maxPathSum(TreeNode* root) {
        dfs(root);
        for (int val : maxPath) {
            cout << val << " ";
        }
        cout << endl;
        return ans;
    }

private:
    Pair dfs(TreeNode* root) {
        if (root == nullptr) return Pair(0, vector<int>());

        Pair l = dfs(root->left);
        Pair r = dfs(root->right);
        int res = root->val;
        vector<int> path;

        //处理本次回溯答案单条路径 左右只能选一或者只有中间节点
        if (l.sum > 0 && l.sum > r.sum) {
            res += l.sum;
            path = l.path;
            path.push_back(root->val);
        } else if (r.sum > 0 && r.sum > l.sum) {
            res += r.sum;
            path.push_back(root->val);
            path.insert(path.end(), r.path.begin(), r.path.end());
        } else {
            path.push_back(root->val);
        }

        //更新答案
        if (res > ans) {
            ans = res;
            maxPath = path;
        }

        if (l.sum + r.sum + root->val > ans) {
            ans = l.sum + r.sum + root->val;
            //左中右赋值
            vector<int> tmp = l.path;
            tmp.push_back(root->val);
            tmp.insert(tmp.end(), r.path.begin(), r.path.end());
            maxPath = tmp;
        }

        return Pair(res, path);
    }
};

72. 编辑距离#

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

    }
};

93. 复原 IP 地址#

class Solution {
public:
    vector<string> res;
    vector<string> restoreIpAddresses(string s) {
        dfs(s,0,0,"");
        return res;
    }

    void dfs(string& s,int idx,int cnt,string path){
        if(idx==s.size()){
            if(cnt==4){
                path.pop_back();
                res.push_back(path);
            }
        }
        if(cnt==4) return;
        for(int i=idx,num=0;i<s.size();i++){
            if(i>idx&&s[idx]=='0') break; //前导0:遍历到大于当前函数的位置而且当前函数进来的时候已经是0
            num=num*10+s[i]-'0';
            
            if(num<=255)
            dfs(s,i+1,cnt+1,path+to_string(num)+'.');
            else return ;
            

        }
    }
};

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

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode *dummy = new ListNode(0);
        dummy->next = head;
        ListNode *fast = dummy;
        ListNode *slow = dummy;

        for(int i=0;i<n;i++){//双指针
            fast=fast->next;
        }
        while(fast->next){
            fast=fast->next;
            slow=slow->next;
        }

        slow->next = slow->next->next;

        return dummy->next;
    }
};

1143. 最长公共子序列#

class Solution {
public:
    int longestCommonSubsequence(string text1, string text2) {
        int n=text1.size(),m=text2.size();
        text1 = " "+text1;
        text2 = " "+text2;
        vector< vector<int> >f(n+1,vector<int>(m+1,0));
        for(int i=1;i<=n;i++){  
            for(int j=1;j<=m;j++){
                //f[i][j]表示串1到i,串2到j的时候最长公共子序列的长度
                f[i][j]=max(f[i-1][j],f[i][j-1]);
                f[i][j]=max(f[i][j],f[i-1][j-1]+(text1[i]==text2[j]));//求子序列!!! 不是编辑距离

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

94. 二叉树的中序遍历 (迭代实现)#

//迭代实现 (用栈保存左节点)
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        TreeNode *predecessor = nullptr;

        while (root != nullptr) {
            if(!root->left){//没有左节点就走右节点
                res.push_back(root->val);
                root=root->right;
            }else{
                predecessor=root->left;//找到左子树最右节点 
                while(predecessor->right&&predecessor->right!=root){//要么走回root说明之前设置过 右节点为空
                    predecessor=predecessor->right;
                }

                if(predecessor->right==nullptr){//第一次来 设置他的节点后,root往左走
                    predecessor->right=root;
                    root=root->left;
                }
                else{//左子树的最右边节点只会自己 说明不是第一次来  已经走完左子树。设置null然后往右走
                    res.push_back(root->val);
                    predecessor->right=nullptr;
                    root=root->right;
                }
            }
        }
        return res;
    }
};


4. 寻找两个正序数组的中位数#

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int len=nums1.size()+nums2.size();
        if(len%2==0){
            auto left=findKth(nums1,0,nums2,0,len/2);
            auto right=findKth(nums1,0,nums2,0,len/2+1);
            return (left+right)/2.0;
        } 
        else 
        return  findKth(nums1,0,nums2,0,len/2+1);
    }
    //递归函数:找两正序数组中第K小的元素,endlen为上次删到的第几个元素 2个边界条件 注意下标=第几个元素k-1
    int findKth(vector<int>&nums1,int endlen1,vector<int>& nums2,int endlen2,int k){
        if(nums1.size()-endlen1>nums2.size()-endlen2) return findKth(nums2,endlen2,nums1,endlen1,k);
        if(endlen1==nums1.size()) return nums2[endlen2+k-1];
        if(k==1) return min(nums1[endlen1],nums2[endlen2]);

        int len1=min(endlen1+k/2,int(nums1.size()));
        int len2=endlen2+k/2;

        if(nums1[len1-1]<nums2[len2-1]){
            return findKth(nums1,len1,nums2,endlen2,k-(len1-endlen1));
        }else{
            return findKth(nums1,endlen1,nums2,len2,k-(len2-endlen2));
        }

    }
};

148. 排序链表#

class Solution {
public:
    ListNode* sortList(ListNode* head) {
        if(!head||!head->next) return head;
        
        return merge(head);
    }
    ListNode* findmid(ListNode* head){
        auto fast=head,slow=head;
        while(fast->next&&fast->next->next){
            slow=slow->next;
            fast=fast->next->next;
        }
        return slow;
    }
    ListNode* merge(ListNode* head){
        if(!head||!head->next) return head;
        auto mid=findmid(head);
        auto head2=mid->next;
        mid->next=nullptr;
        auto l1=merge(head);
        auto l2=merge(head2);
        
        return merge(l1,l2);
    }
    ListNode* merge(ListNode* l1,ListNode* l2){
        if(!l1) return l2;
        if(!l2) return l1;
        if(l1->val<l2->val){
            l1->next=merge(l1->next,l2);
            return l1;
        }else{
            l2->next=merge(l1,l2->next);
            return l2;
        }
        
    }
};

31. 下一个排列#

class Solution {
public:
    void nextPermutation(vector<int>& nums) {
        int n=nums.size();
        if(n==1) return ;
        int i=0,j=0;
        for(i=n-2;i>=0;i--){
            if(nums[i]<nums[i+1]) break;//后往前走找到山峰的左边
        }

        if(i==-1){
            reverse(nums.begin(),nums.end());//找不到说明已经升序
        }else{
            for(j=n-1;j>i;j--){//
                if(nums[j]>nums[i]) break;
            }
            swap(nums[i],nums[j]);//找到一个比i大一点的值 然后交换
            reverse(nums.begin()+i+1,nums.end());//让i+1后面位置都逆序保留最大的排序空间
        }
    }
};

232. 用栈实现队列#

class MyQueue {
public:
    stack<int>in;
    stack<int>out;
    MyQueue() {
    
    }
    
    void push(int x) {
        in.push(x);
    }
    
    int pop() {
        if(out.empty()){
            while(in.size()){
                auto t=in.top();
                in.pop();
                out.push(t);
            }
        }
        auto t=out.top();
        out.pop();
        return t;

    }
    
    int peek() {
        if(out.empty()){
            while(in.size()){
                auto t=in.top();
                in.pop();
                out.push(t);
            }
        }
        auto t=out.top();
        // out.pop();
        return t;
    }
    
    bool empty() {
        if(!in.empty()){
            return false;
        }
        if(!out.empty()) return false;
        return true;
    }
};

/**
 * Your MyQueue object will be instantiated and called as such:
 * MyQueue* obj = new MyQueue();
 * obj->push(x);
 * int param_2 = obj->pop();
 * int param_3 = obj->peek();
 * bool param_4 = obj->empty();
 */

8. 字符串转换整数 (atoi)#

class Solution {
public:
    int myAtoi(string s) {
        //处理空格
        int k=0;
        while(k<s.size()&&s[k]==' ') k++;
        if(k==s.size()) return 0;
        
        //处理符号
        int sign=1;
        if(s[k]=='-') sign=-1,k++;
        else if(s[k]=='+') k++;

        
        int res=0;
        while(k<s.size()&&s[k]>='0'&&s[k]<='9'){
            auto t=s[k]-'0';
            if(sign>0&&res>(INT_MAX-t)/10 ) return INT_MAX;
            if(sign<0&&-res<(INT_MIN+t)/10) return INT_MIN;
            if(-res*10-t==INT_MIN) return INT_MIN;//特别处理 否则下面*10+t就溢出
            res=res*10+t;
            k++;
            
        }   

        return res*sign;     
    }
};

22. 括号生成#

class Solution {
public:
    vector<string>res;
    vector<string> generateParenthesis(int n) {
        dfs(0,0,n,"");   
        return res;
    }
    void dfs(int l,int r,int n,string s){
        if(l==n&&r==n) {
            res.push_back(s);
        }
        if(l>n||r>n) return ;

        if(l<n) dfs(l+1,r,n,s+"(");
        if(l>r&&r<n) dfs(l,r+1,n,s+")");
    }
    
};

69. x 的平方根#

class Solution {
public:
    int mySqrt(int x) {
        int  ans=0,l=0,r=x;
        while(l<r){
            int mid=(l+1ll+r)/2;//注意这里+1的同时也让下面/mid不是/0
            if(mid<=x/mid){
                l=mid;
            }else{
                r=mid-1;
            }
        }
        return r;
    }
};

2. 两数相加#

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
 //从左到右添加
class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        auto dummy= new ListNode(),cur=dummy;//dummy虚拟头结点压根不会用,cur为当前处理到的新链表节点
        int t=0;
        while(l1||l2||t){//关键
            if(l1) t+=l1->val,l1=l1->next;
            if(l2) t+=l2->val,l2=l2->next;
            cur->next=new ListNode(t%10);
            t/=10;
            cur=cur->next;
        }
        return dummy->next;
    }
};

70. 爬楼梯#

物品体积是1或2,体积为楼层,价值为次数

class Solution {
public:
    //输出路径
    int cnt = 0; vector<string> ans;
    int climbStairs(int n) {
         dfs(n, 0, "0");
        for (auto& s : ans) { cout << s << endl; }
        return cnt;
    }

    void dfs(int n, int cur, string s) { 
        if (cur == n) { cnt++; ans.push_back(s); return; } 
        if (cur > n) return; 
        dfs(n, cur + 1, s + to_string(cur + 1)); 
        dfs(n, cur + 2, s + to_string(cur + 2)); 
    } 
        
    走一层不能连续走两次
    dp[i][0]:走1阶到i层 dp[i][1]:走2阶到i层 
    dp[i][0] = dp[i - 1][1] 
    dp[i][1] = dp[i - 2][0] + dp[i - 2][1]
};

239. 滑动窗口最大值#

class Solution {
public:
     vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        int n = nums.size();
        deque<int> q;//开一个双端队列     

        for (int i = 0; i < k; ++i) {//处理前k个
            while(q.size()&&nums[i]>nums[q.back()] ){
                q.pop_back();
                //单调队列而且求最大值 所以后面进入的比上一个进入队的还要大说明队上个进入的这个值肯定用不上 
                //直接删去 
            }
            q.push_back(i);//注意存的是端点
        }

        vector<int> ans = {nums[q.front()]};
        for (int i = k; i < n; ++i) {
            while(q.size()&&nums[i]>nums[q.back()]){
                q.pop_back();
            }
            q.push_back(i);//队列存的是递减的值的下表 对头最大
            while(q.front()<=i-k){//左边界
                q.pop_front();
            }
            ans.push_back(nums[q.front()]);//对列前面的是答案 因为是最大之

        }
        return ans;
    }
};

165. 比较版本号#

class Solution {
public:
    int compareVersion(string v1, string v2) {
        for(int i=0,j=0;i<v1.size()||j<v2.size();){
            int a=i,b=j;
            while(a<v1.size()&&v1[a]!='.') a++;
            while(b<v2.size()&&v2[b]!='.') b++;

            int x= a==i?0:stoi(v1.substr(i,a-i));
            int y= b==j?0:stoi(v2.substr(j,b-j));

            if(x>y) return 1;
            else if(x<y) return -1;
            else {
                i=a+1;
                j=b+1;
            }
        
        }
        return 0;
    }
};

41. 缺失的第一个正数#

class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        int n=nums.size();
        for(auto &x:nums){
            if(x<=0) x=nums.size()+1;
        } 
        for(int i=0;i<nums.size();i++){
            int t=abs(nums[i]);
            if(t>=1&&t<=nums.size()) {
                nums[t-1]=-abs(nums[t-1]);
            }
        }

        for(int i=0;i<nums.size();i++){
            if(nums[i]>0) return i+1;
        }
        return nums.size()+1;
    }
};

322. 零钱兑换#

class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        vector<int>f(amount+1,1e8);
        f[0]=0;
        for(auto v:coins){
            for(int j=v;j<=amount;j++){//多重背包
                f[j]=min(f[j],f[j-v]+1);
            }
        }   
        if(f[amount]==1e8) return -1;
        return f[amount];
    }
};

76. 最小覆盖子串#

class Solution {
public:
    string minWindow(string s, string t) {
        unordered_map<char,int>ht,hs;//表示两个字符串的哈希
        for(char c:t) ht[c]++;
        string res;
        int cnt=0;//窗口中已经满足t串的字符数 cnt==t.size()记录答案
        for(int l=0,r=0;r<s.size();r++){
            hs[s[r]]++;
            if(hs[s[r]]<=ht[s[r]]) ++cnt;
            while(l<r&&hs[s[l]]>ht[s[l]]) hs[s[l++]]--;//左指针超了 窗口右移
            if(cnt==t.size()){
                if(res==""||res.size()>r-l+1) res=s.substr(l,r-l+1);
            }
        }
        return res;
    }
};

106. 从中序与后序遍历序列构造二叉树#

class Solution {
public:
    unordered_map<int,int>pos;
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        for(int i=0;i<inorder.size();i++) pos[inorder[i]] = i;//哈希表
        return build(preorder,inorder,0,preorder.size()-1,0,inorder.size()-1);

    }
    //建树 pre的左右边界,in的左右边界
    TreeNode* build(vector<int>&preorder,vector<int>&inorder,int pl,int pr,int il,int ir){
        if(pl > pr) return nullptr;
        auto root = new TreeNode(preorder[pl]);//先序遍历就是根节点
        int k= pos[root->val];//再到中序遍历里面找为止
        root->left = build(preorder,inorder,pl+1,pl+1+(k-1-il),il,k-1);//通过中序数组计算出先序跨越的长度(中点前一个-1)-(下次左边界)=(k-1)-(il)=(pl+1+(k-1-il)-(pl+1))= (k-1)-(il)
        root->right = build(preorder,inorder,pl+1+(k-1-il)+1,pr,k+1,ir);
        return root;
    }
};

3. 字符串相乘#

class Solution {
public:
    string multiply(string num1, string num2) {
        vector<int>A,B;
        int n=num1.size(),m=num2.size();
        for(int i=n-1;i>=0;i--) A.push_back(num1[i]-'0');
        for(int i=m-1;i>=0;i--) B.push_back(num2[i]-'0');

        vector<int>c(n+m);
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                c[i+j]+=A[i]*B[j];
            }   
        }

        int add=0;
        for(int i=0;i<c.size();i++){
            add+=c[i];
            c[i]=add%10;
            add/=10;
        }

        int k=c.size()-1;
        while(k>0&&!c[k]) k--;
        
        string res;
        while(k>=0) res+='0'+c[k--];

        return res;
    }
};

155. 最小栈#

class MinStack {
public:
    stack<int>x_stack;
    stack<int>min_stack;
    MinStack() {
       min_stack.push(INT_MAX);//因为下面对minst有取top的操作 直接让他变成top
    }
    
    void push(int val) {
        x_stack.push(val);
        min_stack.push(min(val,min_stack.top()));//为了少点判断 最小栈直接放入对顶最小值
    }
    
    void pop() {     
        x_stack.pop();
        min_stack.pop();//一起出
    }
    
    int top() {
        return x_stack.top();
    }
    
    int getMin() {
        return min_stack.top();
    }
};

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

151. 反转字符串中的单词#

class Solution {
public:
    string reverseWords(string s) {
        // 反转整个字符串
        reverse(s.begin(), s.end());

        int n = s.size();
        int idx = 0;
        for (int start = 0; start < n; ++start) {
            
            if (s[start] != ' ') {
                // 填一个空白字符然后将idx移动到下一个单词的开头位置
                if (idx != 0) s[idx++] = ' ';

                // 循环遍历至单词的末尾
                int end = start;
                while (end < n && s[end] != ' ') s[idx++] = s[end++];

                // 反转整个单词
                reverse(s.begin() + idx - (end - start), s.begin() + idx);

                // 更新start,去找下一个单词
                start = end;
            }
        }
        s.erase(s.begin() + idx, s.end());
        return s;
    }

};

101. 对称二叉树#

class Solution {
public:

    bool isSymmetric(TreeNode* root) {
        if(!root) return false;        
        return dfs(root->left,root->right);
    }
    
    bool dfs(TreeNode* left , TreeNode* right){
        if(!left&&!right) return true;
        if(!left||!right||right->val!=left->val) return false;
        return dfs(left->left,right->right)&&dfs(left->right,right->left);
    }

};

110. 平衡二叉树#

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    bool ans=true;//全局作为答案
    bool isBalanced(TreeNode* root) {
        if(!root) {
            ans=true;
            return ans;
        }
        dfs(root);
        return ans;
    }
    int dfs(TreeNode* root){
        if(!root) return 0;
        int l=dfs(root->left),r=dfs(root->right);
        if(abs(l-r) >1) ans=false;
        return max(l,r)+1;    
    }
};

39. 组合总和#

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

};

470. 用 Rand7() 实现 Rand10()#

保证数字概率一样,并且能返回对应的数组就可以

int rand10() {
        int first, second;
        while ((first = rand7()) >2); 
        while ((second = rand7()) > 5);
        return (first-1)*5+second;
    }

int rand100() {
        int first, second,third;
        while ((first = rand7()) >4);
        while ((second = rand7()) > 5);
       while ((third = rand7()) > 5);
        return (first-1)*25+(second-1)*5+third;//注意-1 保证是(0*25)开始,否则就从1*25开始
    }

162. 寻找峰值#

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;
    }
};

48. 旋转图像#

718. 最长重复子数组#

class Solution {
public:
    int findLength(vector<int>& nums1, vector<int>& nums2) {
        int n=nums1.size(),m=nums2.size();
        vector<vector<int>>dp(n+1,vector<int>(m+1,0));
        int res=0;
        for(int i=n-1;i>=0;i--){
            for(int j=m-1;j>=0;j--){
                dp[i][j]= nums1[i]==nums2[j]?dp[i+1][j+1]+1:0;//dp[i][j] 表示 A[i:] 和 B[j:] 的最长公共前缀
                res=max(res,dp[i][j]);//这里答案保存下来了 
            }
        }
        return res;
    }
};

224. 基本计算器#

227. 基本计算器 II#

class Solution {
public:
    deque<char>q;//全局
    int calculate(string s) {
        for(auto x:s) if(x!=' ')  q.push_back(x);
        q.push_back('#');//方便你就算最后的数
        return dfs();
    }
    long long dfs(){
        long long  prev=0,num=0,sum=0;//前一个符号右边的数 num当前处理的左边的数 sum:前一个符号左边的值 
        char prevops='+';
        while(q.size()){
            char c= q.front();
            q.pop_front();
            if(isdigit(c)){
                num=num*10+c-'0';
            }
            else if(c=='('){
                num = dfs();
            }
            else{//如果是其他符号就要处理前一个符号 2+2*3+1
                switch(prevops){
                    case '+':
                        sum+= prev;
                        prev=num;
                        break;

                    case '-':
                        sum+= prev;
                        prev = -num;
                        break;
                    
                    case '*':
                        prev *= num;
                        break;
                    case '/':
                        prev /= num;
                        break;
                }

                if(c==')') break;
                prevops =c;
                num=0;
            }
        } 
        return prev+sum;
    }

};
posted @   liang302  阅读(21)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示
主题色彩