2022-05-21Leetcode856-543-692-1091-21-18-16-172-28-151-223

856. 括号的分数

模拟
参考https://leetcode.cn/problems/score-of-parentheses/solution/gua-hao-de-fen-shu-by-leetcode/475577

class Solution {
public:
    int scoreOfParentheses(string s) {
        int n=s.size();
        stack<int> st;
        for(int i=0; i<n; ++i){
            if(s[i]=='('){
                st.push(0);
            }
            else{
                if(st.top()==0){//()情况,弹出左括号,算出来1进栈
                    st.pop();
                    st.push(1);
                }
                else{//(xxxx)情况,里面遇到左括号之前加和,最后乘2进栈
                    int tmp=0;
                    while(!st.empty() && st.top()!=0){
                        tmp+=st.top();
                        st.pop();
                    }
                    st.pop();//弹出左括号
                    st.push(2*tmp);
                }
            }
        }
        int ans=0;
        while(!st.empty()){
            ans+=st.top();
            st.pop();
        }
        return ans;
    }
};

543. 二叉树的直径

最大深度,递归解法,复杂度高。
deep算最大深度,左子最大深度+右子最大深度和递归左子的解,递归右子的解,3者取最大。

class Solution {
public:
    int deep(TreeNode* root){
        if(!root) return 0;
        return 1+max(deep(root->left), deep(root->right));
    }
    int diameterOfBinaryTree(TreeNode* root) {
        if(!root) return 0;
        if(!root->left && !root->right) return 0;
        return max(deep(root->left)+deep(root->right),max(diameterOfBinaryTree(root->left), diameterOfBinaryTree(root->right)));
    }
};

改为把直径更新放在deep里面就不用重复计算

class Solution {
public:
    int ans=0;
    int deep(TreeNode* root){
        if(!root) return 0;
        int l=deep(root->left);
        int r=deep(root->right);
        ans=max(ans, l+r);
        return max(l, r)+1;
    }
    int diameterOfBinaryTree(TreeNode* root) {
        int d=deep(root);
        return ans;
    }
};

剑指 Offer II 092. 翻转字符

DP解法,出0的时候更新dp,dp的值是当前位置翻转前面所有的1和翻转当前位置的0所需代价的最小值,每次更新dp的时候,可以认为前一个时刻的dp已经把前面整理成单调增了,所以dp更新只看当下位置0翻转和one值。
参考https://leetcode.cn/problems/cyJERH/solution/zhe-ge-dong-tai-gui-hua-jue-liao-by-shix-pe1l/

class Solution {
public:
    int minFlipsMonoIncr(string s) {
        int one=0;
        int dp=0;
        int n=s.size();
        for(int i=0; i<n; ++i){
            if(s[i]=='0'){
                dp=min(one,dp+1);
            }
            else{
                one++;
            }
        }
        return dp;
    }
};

692. 前K个高频单词

哈希表+自定义排序,空间消耗大,纯业务代码写法。
改进是不用sort,按类似top k的写法,把原来的比较符号改为自定义比较,可以用冒泡k次。
优先队列是题解写法。

class Solution {
public:
    static bool cmp(pair<string, int> p1, pair<string, int> p2){
        //这个自定义compare要带static
        if(p1.second>p2.second) return true;
        else if(p1.second<p2.second) return false;
        //频率大的在前,小的在后
        else{//频率相同,比较字典序,字典序在前的在前
            string s1=p1.first, s2=p2.first;
            if(s1.compare(s2)<0) return true;//注意是s2字典序在s1前的话<0,相同的=0,s2更大的话>0
            else return false;
        }
    }

    vector<string> topKFrequent(vector<string>& words, int k) {
        unordered_map<string, int> mp;//word,频率
        vector<string> v;
        for(auto word:words){
            mp[word]++;
            if(mp[word]==1)
            v.push_back(word);//出现的所有词
        }
        vector<pair<string, int>> v2;//用于排序
        for(auto word:v){
            v2.push_back({word, mp[word]});
        }
        sort(v2.begin(), v2.end(), cmp);//排序
        vector<string> ans;
        for(int i=0; i<k; ++i){//取出前k个
            ans.push_back(v2[i].first);
        }
        return ans;
    }
};

1091. 二进制矩阵中的最短路径

BFS,类似迷宫,这个是nxn迷宫,相当简化,8个方向版本
套路就是先定义8个方向向量,queue存三元组<x,y,value>,visited存当前坐标是否已遍历

class Solution {
public:
    vector<int> x={0,0,-1,-1,-1,1,1,1};
    vector<int> y={1,-1,0,-1,1,0,-1,1};
    int shortestPathBinaryMatrix(vector<vector<int>>& grid) {
        int n=grid.size();
        int m=n;
        if(n==1){
            if(grid[0][0]==0) return 1;
            else return -1;
        }
        queue<tuple<int, int, int>> q;//横坐标,纵坐标,到当前点的最短路径
        //三元组存进去,就不用分层存了
        vector<vector<int>> visited(n, vector<int>(n,0));//visited防止重复计算
        if(grid[0][0]==1) return -1;
        visited[0][0]=1;
        q.push({0,0,1});
        while(!q.empty()){
            auto tu=q.front(); q.pop();
            int i=get<0>(tu);
            int j=get<1>(tu);
            int value=get<2>(tu);
            for(int k=0; k<8; ++k){
                int xn=x[k]+i, yn=y[k]+j;
                if(xn<0 || xn>=n || yn<0 || yn>=m || grid[xn][yn]==1 || visited[xn][yn]==1) continue;
                //出界就跳过
                else{
                    if(xn==n-1 && yn==n-1){
                        return value+1;
                    }
                    else{
                        q.push({xn, yn, value+1});
                        visited[xn][yn]=1;
                    }
                }
            }
        }
        return -1;
    }
};

204. 计数质数

class Solution {
public:
    int countPrimes(int n) {
       vector<int> v(n, 1);
       int ans=0;
       for(int i=2; i<n; ++i){
           if(v[i]){
               ans++;
               if((long long)i*i<=n){
                   for(int j=i*i; j<n; j+=i){
                       v[j]=0;
                   }
               }
           }
       }
       return ans; 
    }
};

23. 合并K个升序链表

注意:这题的合并是原链表节点合并,不用new一个节点接在后面。

class Solution {
public:
    ListNode* mergeTwolists(ListNode* l1, ListNode* l2){
        if(!l1 || !l2) return l1?l1:l2;
        ListNode* head=new ListNode(0);
        ListNode* cur=head;
        while(l1 && l2){
            if(l1->val < l2->val){
                cur->next=l1;
                l1=l1->next;
                cur=cur->next;
            }
            else{
                cur->next=l2;
                l2=l2->next;
                cur=cur->next;
            }
        }
        if(l1) cur->next=l1;
        if(l2) cur->next=l2;
        return head->next;
    }
    ListNode* merge(vector<ListNode*>& lists, int left, int right){
        if(left==right) return lists[left];
        if(left>right) return nullptr;
        int mid=(left+right)/2;
        return mergeTwolists(merge(lists, left, mid), merge(lists, mid+1, right));
    }
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        int n=lists.size();
        return merge(lists, 0, n-1);
    }
};

18. 四数之和

先排序,再遍历n直到剩下最后两个,两数和用双指针,注意不留重复,所以每一层都要去重。n数和都可以用同一套方法做

参考https://leetcode.cn/problems/4sum/solution/shuang-zhi-zhen-jie-fa-can-zhao-san-shu-zhi-he-ge-/

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        int a,b,c,d,n=nums.size();
        vector<vector<int>> ans;
        sort(nums.begin(), nums.end());//排序双指针
        for(int i=0; i<=n-4; ++i){
            //vector<int> tmp;
            if(i>0 && nums[i]==nums[i-1]) continue;
            a=nums[i];
            for(int j=i+1; j<=n-3; ++j){
                if(j>i+1 && nums[j]==nums[j-1]) continue;
                b=nums[j];
                int left=j+1, right=n-1;
                int newTarget=target-a-b;
                while(left<right){
                    if(nums[left]+nums[right]<newTarget) left++;
                    else if(nums[left]+nums[right]>newTarget) right--;
                    else{
                        ans.push_back({a,b,nums[left], nums[right]});
                        while(left<right&&nums[left+1]==nums[left]) left++;
                        while(left<right&&nums[right-1]==nums[right]) right--;
                        left++;
                        right--;
                    }
                }
            }
        }
        return ans;
    }
};

16. 最接近的三数之和

和上面差不多,没有要存不重复的,所以不判断重复,注意一个保存最小差值就可。

class Solution {
public:
    int threeSumClosest(vector<int>& nums, int target) {
        int ans;
        int n=nums.size();
        int mincha=INT_MAX;
        sort(nums.begin(), nums.end());
        for(int i=0; i<=n-3; ++i){
            int left=i+1, right=n-1;
            while(left<right){
                int sum=nums[i]+nums[left]+nums[right];
                if(abs(sum-target)<mincha){
                    mincha=abs(sum-target);
                    ans=sum;
                }
                if(sum<target) left++;
                else if(sum>target) right--;
                else return target;
            }
        }
        return ans;
    }
};

172. 阶乘后的零

找5因子的个数

class Solution {
public:
    int trailingZeroes(int n) {
        if(n==0) return 0;
        int ans=0;
        for(int i=5; i<=n; i+=5){
            for(int j=i; j%5==0; j/=5){
                ans++;
            }
        }
        return ans;
    }
};

28. 实现 strStr()

用compare匹配,自己实现可以改个KMP或者朴素匹配,如果不自己实现,就不必写这种题…

class Solution {
public:
    int strStr(string haystack, string needle) {
        int m=haystack.size(), n=needle.size();
        if(n==0) return 0;
        if(m<n) return -1;
        for(int i=0; i<=m-n; ++i){
            string str1=haystack.substr(i,n);
            if(str1.compare(needle)==0) return i;
        }
        return -1;
    }
};

151. 颠倒字符串中的单词

class Solution {
public:
    string reverseWords(string s) {
        reverse(s.begin(), s.end());
        int n=s.size();
        string ans;
        int k=0;
        while(s[k]==' ') k++;
        while(k<n){
            if(s[k]!=' '){
                string tmp;
                while(k<n && s[k]!=' '){
                    tmp=s[k]+tmp;
                    k++;
                }
                if(tmp.size()) ans=ans+tmp+" ";
            }
            k++;
        }      
        if(ans.size()){
            ans=ans.substr(0, ans.size()-1);
        } 
        return ans; 
    }
};

223. 矩形面积

class Solution {
public:
    int computeArea(int ax1, int ay1, int ax2, int ay2, int bx1, int by1, int bx2, int by2) {
        //s1, s2
        //交叉面积
        int s1= (ax1-ax2)*(ay1-ay2), s2=(bx1-bx2)*(by1-by2);
        int x=min(ay2,by2)-max(ay1,by1), y=min(ax2,bx2)-max(ax1,bx1);
        int s=s1+s2-max(x,0)*max(y,0);
        return s;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值