• 作者: 负雪明烛
  • 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. 硬盘SSD、HDD和SSHD都是什么意思?哪种类型硬盘最好?

    硬盘分类:(1)HHD 机械硬盘(Mechanical hard disk)(2)SSD 固态硬盘(solid state drive/disk)(3)SSHD 混合硬盘,说白了就是HDD+SSD=S ...

  2. Python—python2.7.5升级到2.7.14或者直接升级到3.6.4

    python2.7.5升级到2.7.14 1.安装升级GCC yum install -y gcc* openssl openssl-devel ncurses-devel.x86_64  bzip2 ...

  3. linux 网络配置管理

    [1]网络配置基础 (1)用户既可以通过命令行的方式,也可以通过友好的图形界面,轻松完成网络配置. (2)实现Linux网络配置的惟一目标就是修改系统中众多的网络配置文件, 如/etc/interfa ...

  4. keepalived+nginx安装

    安装keepalived+nginx做为公司服务器前端高可用反向代理安装nginx 1.yum install -y pcre pcre-devel gcc-c++ zlib zlib-devel o ...

  5. Volatile的3大特性

    Volatile volatile是Java虚拟机提供的轻量级的同步机制 3大特性 1.保证可见性 当多个线程同时访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值 案例代码 ...

  6. 日常Java 2021/10/12

    封装 在面向对象程式设计方法中,封装是指-种将抽象性函式接口的实现细节部分包装.隐藏起来的方法 封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问 要访问该类的代码和数据,必 ...

  7. mysql锁相关讲解及其应用

    一.mysql的锁类型 了解Mysql的表级锁 了解Mysql的行级锁 (1) 共享/排它锁(Shared and Exclusive Locks) 共享锁和排他锁是InnoDB引擎实现的标准行级别锁 ...

  8. 用户创建firefox配置文件

    1.打开cmd进放 firefox.exe所在的目录 如:D:\>cd D:\Mozilla Firefox 2.运行如命令:D:\Mozilla Firefox>firefox.exe ...

  9. 【编程思想】【设计模式】【行为模式Behavioral】Specification

    Python版 https://github.com/faif/python-patterns/blob/master/behavioral/specification.py #!/usr/bin/e ...

  10. OpenStack之二: 安装OpenStack的yum源及相关组件

    #: 在所有节点执行 [root@localhost ~]# yum install centos-release-openstack-stein -y #: 安装相关组件(只在管理端和计算几点安装) ...