• 作者: 负雪明烛
  • id: fuxuemingzhu
  • 公众号:每日算法题
  • 本文关键词:LeetCode,力扣,算法,算法题,字符串,双指针,刷题群

题目地址:https://leetcode.com/problems/longest-repeating-character-replacement/description/

题目描述

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.

题目大意

求一个字符串修改k个字符后,能够成的最长的相同字符组成的连续子序列。

解题方法

双指针

首先需要区分两个概念:子串(子数组)子序列。这两个名词经常在题目中出现,非常有必要加以区分。子串sub-string(子数组 sub-array)是连续的,而子序列 subsequence 可以不连续。

我读完今天这个题目之后,脑子里把题目转成了另外一个表达方式:求字符串中一个最长的区间,该区间内的出现次数较少的字符的个数不超过 k。

上面的表达方式跟题目是等价的,抽象成这种表达方式的好处是让我们知道这是一个区间题,求子区间经常使用的方法就是双指针

《挑战程序设计竞赛》这本书中把双指针叫做「虫取法」,我觉得非常生动形象。因为双指针移动的过程和虫子爬动的过程非常像:前脚不动,把后脚移动过来;后脚不动,把前脚向前移动

我分享一个双指针的模板,能解决大多数的双指针问题:

def findSubstring(s):
N = len(s) # 数组/字符串长度
left, right = 0, 0 # 双指针,表示当前遍历的区间[left, right],闭区间
counter = collections.Counter() # 用于统计 子数组/子区间 是否有效
res = 0 # 保存最大的满足题目要求的 子数组/子串 长度
while right < N: # 当右边的指针没有搜索到 数组/字符串 的结尾
counter[s[right]] += 1 # 增加当前右边指针的数字/字符的计数
while 区间[left, right]不符合题意:# 此时需要一直移动左指针,直至找到一个符合题意的区间
counter[s[left]] -= 1 # 移动左指针前需要从counter中减少left位置字符的计数
left += 1 # 真正的移动左指针,注意不能跟上面一行代码写反
# 到 while 结束时,我们找到了一个符合题意要求的 子数组/子串
res = max(res, right - left + 1) # 需要更新结果
right += 1 # 移动右指针,去探索新的区间
return res

简单介绍上面的模板,模板的思想是:以右指针作为驱动,拖着左指针向前走。右指针每次只移动一步,而左指针在内部 while 循环中每次可能移动多步。右指针是主动前移,探索未知的新区域;左指针是被迫移动,负责寻找满足题意的区间。

模板的整体思想是:

  1. 定义两个指针 leftright 分别指向区间的开头和结尾,注意是闭区间;定义 counter 用来统计该区间内的各个字符出现次数;
  2. 第一重 while 循环是为了判断 right 指针的位置是否超出了数组边界;当 right 每次到了新位置,需要增加 right 指针的计数;
  3. 第二重 while 循环是让 left 指针向右移动到 [left, right] 区间符合题意的位置;当 left 每次移动到了新位置,需要减少 left 指针的计数;
  4. 在第二重 while 循环之后,成功找到了一个符合题意的 [left, right] 区间,题目要求最大的区间长度,因此更新 resmax(res, 当前区间的长度)
  5. right 指针每次向右移动一步,开始探索新的区间。

模板中为什么不把 counter 放在 while 循环内部呢?因为如果放在 while 内部每次新建一个 counter 变量,统计区间的字符出现次数的时间复杂度是 O(N) ;放在 while 外部,每次增加 right 指向的字符的计数、减少 left 指向的字符的计数的是时间复杂度是 O(1) 。这也是常见的统计区间问题时的技巧。类似的,如果我们要求一个区间的的话,也可以用类似的思想去做。

代码

今天的代码可以直接套用上面的双指针模板,内层的 while 循环中的判断条件该区间内出现次数较少的字符的出现次数是否大于 k 。如果大于 k 的话,说明该区间不符合题意,需要移动 left 指针直至符合题意为止。

如果理解了上面的双指针模板之后,我做了动图帮助理解。

使用 Python2 写的代码如下。

class Solution(object):
def characterReplacement(self, s, k):
"""
:type s: str
:type k: int
:rtype: int
"""
N = len(s)
left, right = 0, 0 # [left, right] 都包含
counter = collections.Counter()
res = 0
while right < N:
counter[s[right]] += 1
while right - left + 1 - counter.most_common(1)[0][1] > k:
counter[s[left]] -= 1
left += 1
res = max(res, right - left + 1)
right += 1
return res

欢迎加入组织

算法每日一题是个互相帮助、互相监督的力扣打卡网站,其地址是 https://www.ojeveryday.com/

想加入千人刷题群的朋友,可以复制上面的链接到浏览器,然后在左侧点击“加入组织”,提交力扣个人主页,即可进入刷题群。期待你早日加入。

欢迎关注我的公众号:每日算法题

日期

2018 年 3 月 12 日
2021 年 2 月 2 日 —— 现在题解的这个动图是我做的第一个动图

【LeetCode】424. 替换后的最长重复字符 Longest Repeating Character Replacement(Python)的更多相关文章

  1. [Swift]LeetCode424. 替换后的最长重复字符 | Longest Repeating Character Replacement

    Given a string that consists of only uppercase English letters, you can replace any letter in the st ...

  2. Java实现 LeetCode 424 替换后的最长重复字符

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

  3. Leetcode 424.替换后的最长重复字符

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

  4. 【LeetCode】424. 替换后的最长重复字符

    424. 替换后的最长重复字符 知识点:字符串,滑动窗口: 题目描述 给你一个仅由大写英文字母组成的字符串,你可以将任意位置上的字符替换成另外的字符,总共可最多替换 k 次.在执行上述操作后,找到包含 ...

  5. 424 Longest Repeating Character Replacement 替换后的最长重复字符

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

  6. [LeetCode] Longest Repeating Character Replacement 最长重复字符置换

    Given a string that consists of only uppercase English letters, you can replace any letter in the st ...

  7. 【leetcode】424. Longest Repeating Character Replacement

    题目如下: Given a string that consists of only uppercase English letters, you can replace any letter in ...

  8. LeetCode 424. Longest Repeating Character Replacement

    原题链接在这里:https://leetcode.com/problems/longest-repeating-character-replacement/description/ 题目: Given ...

  9. Leetcode: Longest Repeating Character Replacement && G 面经

    Given a string that consists of only uppercase English letters, you can replace any letter in the st ...

随机推荐

  1. MariaDB——数据库登录

    登录MariaDB数据库,用root账户和密码: 显示所有数据库列表:其中,information_schema.performance_schema.test.mysql,这4个库表是数据库系统自带 ...

  2. Oracle-判断一个表的一列是否在另一张表的一列存在

    select * from A where exists(select 1 from B where A.a = B.b)  

  3. 22-reverseString-Leetcode

    思路:so easy class Solution { public: string reverseString(string s) { int n = s.size(); for(int i=0;i ...

  4. 2.MaxSubArray-Leetcode

    题目:最大连续子序列和 思路:动态规划 状态转移方程 f[j]=max{f[j-1]+s[j],s[j]}, 其中1<=j<=n target = max{f[j]}, 其中1<=j ...

  5. 【模板】最小费用最大流(网络流)/洛谷P3381

    题目链接 https://www.luogu.com.cn/problem/P3381 题目大意 输入格式 第一行包含四个正整数 \(n,m,s,t\),分别表示点的个数.有向边的个数.源点序号.汇点 ...

  6. C++中Try Catch中的继承

    1.C++中Try Catch简介:我们编译运行程序出错的时候,编译器就会抛出异常.抛出异常要比终止程序灵活许多. 而C++异常是指在程序运行时发生的反常行为,这些行为超出了函数正常功能的范围.当程序 ...

  7. 游戏案例|Service Mesh 在欢乐游戏的应用演变和实践

    作者 陈智伟,腾讯 12 级后台专家工程师,现负责欢乐游戏工作室公共后台技术研发以及团队管理工作.在微服务分布式架构以及游戏后台运维研发有丰富的经验. 前言 欢乐游戏工作室后台是分布式微服务架构,目前 ...

  8. python格式化输出的两种方式对比

    1.%符号方法和format()函数方法 2.对比: 1 print('我今年%d岁' %22.125) 2 print('我今年{0:f}'.format(22.125)) 3 #报错 4 #槽中类 ...

  9. CentOS6+nginx+uwsgi+mysql+django1.6.6+python2.6.6

    1.配置网关 #vi /etc/sysconfig/network NETWORKING=yes(表示系统是否使用网络,一般设置为yes.如果设为no,则不能使用网络,而且很多系统服务程序将无法启动) ...

  10. JConsole可视化工具

    JConsole基本介绍 Jconsole (Java Monitoring and Management Console),一种基于JMX的可视化监视.管理工具.JConsole 基本包括以下基本功 ...