分享

Leetcode5634. 删除子字符串的最大得分[C 题解]:贪心

 印度阿三17 2021-01-10

文章目录

题目

字符串中找出"ab"或者"ba"

样例
在这里插入图片描述
字符串可以分成很多段,[ ab的组合]、其他字母、[ab的组合]、其他字母这样很多段,样例就是 cd[b]c[bbaaabab]可以拆成ab的组合和其他字母。

对于某一段[ab的组合],需要计数a和b的个数:分别记为A和B。比如[abbaaba]其中a的个数A=4,b的个数B=3. 这一段可以操作的数量是min(A,B)=3次,这里的每次操作消耗掉一个a和一个b。而且只要有相邻的a和b就可以操作。

这里我们假定ab的得分大于等于ba的得分,即x≥y。(可以省去一半的思考时间),那么想要得分最大,就需要 删除ab的操作尽可能多。

最多可以删除多少个ab呢?

可以贪心来做。某个位置的a,能否和b配对,取决于其后面是否有b。如果和b相邻那么自然可以配对。我们从后往前遍历,计数b的数量(相当于放在后备箱),往前扫的过程中每遇到一个a,就从后备箱拿出一个b,计数器减1.代表成功配对1个ab。如果后备箱中没有b,这个a就不能配成ab。

这样遍历完之后,最大的ab个数就确定了,而总的操作次数是min(A,B),则操作ba的个数就是min(A,B)-ab个数.然后分别乘以得分x和y即为最大得分。

ac代码

class Solution {
public:
    int maximumGain(string s, int x, int y) {
        //假定x≥y
        if(x<y){
            swap(x,y);
            for(auto& c:s){
                if(c=='a') c='b';
                else if(c=='b') c='a';
            }
        }
       
        int res=0;

        for(int i=0; i< s.size();i  ){ //用i和j来指明某一段[i,j)左闭右开
            if(s[i]!='a' && s[i]!='b') continue;

            int j=i;
            while(j<s.size() && ( s[j]=='a'|| s[j]=='b')) j  ;//执行这一步之后j一定在i后面

            int a=0,b=0,c=0, remain=0;//remain表示后备箱中b的数量
            //c表示找出来ab的数量
            for(int k = j-1; k>= i; k --){ //具体的一段的处理
                if(s[k]=='a'){
                    a  ;
                    if(remain) { //后备箱中还有b
                        remain--;
                        c  ;
                    }
                }else {//s[k]=='b'
                    b  ;
                    remain  ;
                }
            }
            res =c*x  (min(a,b)-c)*y;//加号后面表示"ba"的数量×分数y
             i=j; //这一段结束,遍历下一段
            
        }
        return res;


    }
};

题目链接

Leetcode5634. 删除子字符串的最大得分

来源:https://www./content-1-816401.html

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多