【leetcode】替换后的最长重复字符、将字符串翻转到单调递增

1.替换后的最长重复字符

示例如下:

 

下面我们来分析一下一个例子,其中K = 2

暴力枚举

这里的字符串s是仅由大写字母组成,首先我们尝试用暴力解法的思路来想一下这道题,通过从第一个字符开始进行枚举,如果出现了条件判断不成立,也就是说,需要替换的字符数量已经超过了K个,因此对于本次枚举的字符串再往后的字符就不可能是重复的字符串了,因此在从下一个字符进行枚举。

接下来继续从下一个字符开始枚举:

知道字符串s的末尾,然后在进行找最大重复子串的同时用一个变量记录最大长度即可,这就是暴力枚举。

滑动窗口

如果back走到上图的位置,那么此时已经无法满足替换K个窗口里的字符是该字符串是重复字符了,此时如果继续让back往后走,那么接下来的子串就不可能是重复字符的子串了,因此我们要移动prev:

然后此时窗口内的字符就满足重复字符的子串了,然后继续先后移动back

因此使用滑动窗口的关键是要进行判断:窗口中的子串是否可以不超过K次替换后是重复字符子串。

class Solution {
public:
    int characterReplacement(string s, int k) {
        //开辟一个数组,存储窗口中不同类字符出现的次数
        vector<int> v(26);
        int prev = 0,back = 0;
        int max_count = 0;
        int res = 0;
        while(back < s.length())
        {
            //进窗口
            v[s[back]-'A']++;
            //vector<int> v_copy(v);
            //std::sort(v_copy.begin(),v_copy.end(),std::greater<int>());
            //max_count = v_copy[0];
            max_count = *std::max_element(v.begin(),v.end());
            //判断
            while(back-prev+1-max_count > k)
            {
                //出窗口
                v[s[prev]-'A']--;
                ++prev;
            }
            //更新结果
            res = std::max(res,back-prev+1);
            ++back;
        }
        return res;
    }
};

2.将字符串翻转到单调递增

示例:

 动态规划

下面我们来分析一个示例:

 

通过上面例子的逐个位置分析可以理解到,最小翻转次数就是min(某个位置的前面的1的个数+位置后的0的个数),因此我们可以定义两个数组:dp1,dp0,分别表示某个位置前1的个数,位置后0的个数。

class Solution {
public:
    int minFlipsMonoIncr(string s) {
        //s中1的前缀和,0的后缀和
        vector<int> dp0(s.size());
        vector<int> dp1(dp0);
        int res = INT_MAX;
        for(int i = 1,j = s.size()-2;i<s.size();++i,--j)
        {
            //1的前缀和
            if('1' == s[i-1])
            dp1[i] = dp1[i-1]+1;
            else
            dp1[i] = dp1[i-1];
            //0的后缀和
            if('0' == s[j+1])
            dp0[j] = dp0[j+1]+1;
            else
            dp0[j] = dp0[j+1];
        }
        for(int i = 0;i<dp0.size();++i)
           res = std::min(res,dp0[i]+dp1[i]);
        return INT_MAX == res ? 0 : res;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值