leetcode_[python/C++]_424_Longest Repeating Character Replacement

本文介绍了一种使用滑窗算法求解给定字符串中通过最多k次字符替换能得到的最长重复字符子串的问题。提供了C++及Python两种语言的实现方案,并详细解释了算法流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接
【题目】
Given a string that consists of only uppercase English letters, you can replace any letter in the string with another letter at most k times. Find the length of a longest substring containing all repeating letters you can get after performing the above operations.


Note:
Both the string’s length and k will not exceed 104.

Example 1:

Input:
s = “ABAB”, k = 2

Output:
4

Explanation:
Replace the two ‘A’s with two ‘B’s or vice versa.


Example 2:

Input:
s = “AABABBA”, k = 1

Output:
4

Explanation:
Replace the one ‘A’ in the middle with ‘B’ and form “AABBBBA”.
The substring “BBBB” has the longest repeating letters, which is 4.
Subscribe to see which companies asked this question


【分析】
这道题主要是为了分享一种很不错的解法,叫做滑窗算法,类似我们计算机网络中的发送数据包的滑动窗口移动。
算法思想:
即定义end和begin指针,end -begin即为窗体的长度,始终维护一个窗体,要保证该窗体中:窗体长度 - 最多字母个数 > k,也就是维护窗体中除了个数最多的字符外,其他字符总数不超过k。窗体长度即为最多变换k次之后,最长的相同字母字符串。

class Solution {
public:
    int characterReplacement(string s, int k) {
        int size = s.size();
        vector<int> count(26,0);
        int begin = 0, maxlen = 0, ans = 0;
        for(int end=0;end<size;end++){
            maxlen = max(maxlen,++count[s[end]-'A']);
            while(end - begin + 1 - maxlen > k) count[s[begin++] - 'A']--;//相当于count[s[begin] - 'A']--;  begin ++;
            ans = max(ans,  end - begin + 1);
        }
        return ans;
    }
};

python写法

class Solution(object):
    def characterReplacement(self,s, k):
        """
        :type s: str
        :type k: int
        :rtype: int
        """
        from math import *
        size = len(s)
        count = [0]*26
        begin = 0
        maxlen = 0
        ans = 0
        for end in range(size):
            count[ord(s[end])-ord('A')] = count[ord(s[end])-ord('A')] + 1
            maxlen = max(maxlen,count[ord(s[end])-ord('A')])
            while end - begin + 1 - maxlen > k:
                count[ord(s[begin])-ord('A')] = count[ord(s[begin])-ord('A')] - 1
                begin = begin + 1
            ans = max(ans,end - begin + 1)
        return ans

discuss中有一种利用collections.counters()的做法,很强

class Solution(object):
    def characterReplacement(self, s, k):
        res = lo = 0
        counts = collections.Counter()
        for hi in range(len(s)):
            counts[s[hi]] += 1
            max_char_n = counts.most_common(1)[0][1]
            while (hi - lo - max_char_n + 1 > k):
                counts[s[lo]] -= 1
                lo += 1
            res = max(res, hi - lo + 1)
        return res

这道题一开始看错题目了,以为k是指能改变一种字母多少次,就写了下面这种代码,有点粗糙但是符合这种要求的解法

int characterReplacement(string s, int k) {

        set<char> sets;
        int size = s.size();
        for(int i=0;i<size;i++){
            sets.insert(s[i]);
        }
        char chr;
        set<char>::iterator iter;
        char ans_chr;
        int begin_index = 0;
        int end_index = 0;
        int max = -100000;
        for(iter = sets.begin();iter!= sets.end();iter++){
            chr = *iter;
            vector<int> dp(size,0);
            vector<int> first(sets.size(),0);
            int num[124];
            memset(num,0,sizeof(num));

            for(int i=1;i<size;i++){
                if(num[s[i]] == 0) first[s[i]] = i;
                if(s[i]==chr){
                    dp[i] = dp[i-1];
                    if(i==1 && s[i]!=s[i-1]) dp[i] = 1;
                }
                else{
                    if(num[s[i]] < k){
                        num[s[i]]++;
                        dp[i] = dp[i-1];
                    }
                    else{
                        if(first[s[i]] == 0){
                            dp[i] = i;
                            memset(num,0,sizeof(num));
                            first[s[i]] = i;
                        }
                        else{
                            dp[i] = first[s[i]]+1;
                            memset(num,0,sizeof(num));
                            for(int j = first[s[i]]+1;j<=i;j++){
                                if(num[s[j]] == 0){
                                    first[s[j]] = j;
                                }
                                num[s[j]]++;
                            }
                        }


                    }
                }
            }
            for(int i=0;i<size;i++){
                if(i-dp[i]>max){
                    begin_index = dp[i];
                    end_index = i;
                    max = i - dp[i];
                    ans_chr = chr;
                }
            }

        }
        return max+1;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值