leetcode424替换后的最长重复子串——利用滑动窗口解决范围计数

给你一个仅由大写英文字母组成的字符串,你可以将任意位置上的字符替换成另外的字符,总共可最多替换 次。在执行上述操作后,找到包含重复字母的最长子串的长度。

注意:
字符串长度 和 不会超过 104

示例 1:

输入:
s = "ABAB", k = 2

输出:
4

解释:
用两个'A'替换为两个'B',反之亦然。

示例 2:

输入:
s = "AABABBA", k = 1

输出:
4

解释:
将中间的一个'A'替换为'B',字符串变为 "AABBBBA"。
子串 "BBBB" 有最长重复字母, 答案为 4。

最开始考虑“中心扩散法”。

选定了一个字符s[i]然后指针右移保存最长子串范围和剩余的k。右移时k只要大于0便可以跳过不相同的字符,然后k-=1.

然后分别向两边扩展直到k为0.

很遗憾还有更好的办法,自我刷leetcode以来仅仅见过不超过三次的办法——滑动窗口。

以示例2为例。

选定窗口长度w=2,因为k=1,所以长度<=1的任何子串都可以被换成指定的字符。

统计一个窗口的子串中各个字符的数量,可以用哈希表,也可以用数组。

最后在这个统计数据结构中找到最多的那个,设为n。

如果w-n<=k说明剩下的可以被替换为最多的那个字符,我们把窗口进一步扩大,

否则缩小窗口。

值得一说的是滑动窗口的经典技巧:

比如原来是s【0-3】={A:3,B:1},那么扩大到s【0-4】(宽度为5)时,只需递增新加入的字符={A:3,B:2},

向前缩小时,同样的,递减除去的字符数量即可。

代码如下:

class Solution:
    def find_max(self,arr):
        j,val=-1,-1
        for i,v in enumerate(arr):
            if v>val:
                val=v
                j=i
        return j
    def characterReplacement(self, s, k):
        if s=='':
            return 0
        arr=[0 for _ in range(26)]
        orda=ord('A')
        width=k+1
        i=0
        max_len=k
        for c in s[:width]:
            arr[ord(c)-orda]+=1
        while True:
            j=self.find_max(arr)
            if width-arr[j]<=k:
                max_len=max(max_len,width)
                if i+width<len(s):
                    arr[ord(s[i+width])-orda]+=1
                    width+=1
                else:
                    break
            else:
                arr[ord(s[i])-orda]-=1
                i+=1
                width-=1
        return max_len
其中find_max是个辅助函数,为了找到数据结构里数量最多的字符。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值