目录

  • 424. 替换后的最长重复字符
    • 思考分析1
    • 优化
  • 1004. 最大连续1的个数 III
    • 友情提醒
    • 方法1,基于当前最大频数
    • 方法2,基于历史最大频数

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

https://leetcode-cn.com/problems/longest-repeating-character-replacement/
给你一个仅由大写英文字母组成的字符串,你可以将任意位置上的字符替换成另外的字符,总共可最多替换 k 次。在执行上述操作后,找到包含重复字母的最长子串的长度。

注意:
字符串长度 和 k 不会超过 10^4。
示例 1:

输入:
s = “ABAB”, k = 2
输出:
4
解释:
用两个’A’替换为两个’B’,反之亦然。

示例 2:

输入:
s = “AABABBA”, k = 1
输出:
4
解释:
将中间的一个’A’替换为’B’,字符串变为 “AABBBBA”。
子串 “BBBB” 有最长重复字母, 答案为 4。

思考分析1

需要注意的地方:

1、何时扩充窗口?
当子串符合要求,向右扩充一位。(贪心思想,满足了要求还要继续膨胀)
2、子串达成什么条件能说明符合要求?
如果最大频数 + k >= 当前窗口长度,(也就是说经过k此修改,我们可以将不是出现次数最多的元素修改为频数最高元素,从而变为重复串,并且这个串的长度是大于此时窗口长度的)那么我们认为是符合条件的,此时更新窗口长度,取历史窗口长度与当前窗口长度的较大值
3、什么时候滑动窗口
当子串不满足条件的时候,窗口整体向右滑动一位,窗口长度不会减少。

class Solution {public:int characterReplacement(string s, int k) {int left = 0, right = 0;//当前窗口中元素的最高频数int now_max_freq = 0;int hash_map[26] ={0};//窗口长度最大值int max_window_length = 0;while(right < s.size()){//新加入窗口的元素char c = s[right];//窗口内这个元素对应的频数+1hash_map[c - 'A']++;//找到整个窗口内最大频数for(int i = 0; i < 26; i++)now_max_freq = max(now_max_freq,hash_map[i]);//如果最大频数 + k >= 当前窗口长度,那么我们认为是符合条件的,此时更新窗口长度,取历史窗口长度与当前窗口长度的较大值if(now_max_freq + k >= right - left + 1){max_window_length = max(max_window_length,right - left + 1);}//如果不满足整个条件,我们需要将整个窗口平移else{char d = s[left];hash_map[d - 'A']--;left++;}right++;}return max_window_length;}
};

优化

关于优化,首先得知道一点就是我们之前更新窗口长度的条件:
1、先找这个窗口内的最大频数
2、如果这个频数 + k >= 当前窗口长度,我们选择更新窗口长度
由于在寻找最大频数的时候有个比较过程,并且每次新进来一个字符我们就得重新比较26次。(我们可以优化比较,例如加入备忘录什么的)。但这里我们不需要这样做。
我们只需要找到“历史窗口内元素出现最大频数”,然后观察这个频数 + k 是否 >= 当前窗口长度。
由于这道题目要求求解的是最长重复子串,如果当前窗口最大字符重复个数小于历史窗口的最大字符重复个数,完全可以将此窗口忽略掉,因为它必然不可能是最长重复子串。只有当历史窗口的最大字符重复个数更新时,其最大长度才会进行相应的更新。
现在我们将上面的代码稍作修改,改成如下代码:

class Solution {public:int characterReplacement(string s, int k) {int left = 0, right = 0;//历史最大频数int history_max_freq = 0;int hash_map[26] ={0};int max_window_length = 0;while(right < s.size()){//新加入窗口的元素char c = s[right];hash_map[c - 'A']++;//观察整个元素是不是窗口内出现次数最多的元素,如果是更新history值history_max_freq = max(history_max_freq,hash_map[c - 'A']);if(history_max_freq + k >= right - left + 1){max_window_length = max(max_window_length,right - left + 1);}else{char d = s[left];//窗口左移,被移除的元素在窗口内频数-1hash_map[d - 'A']--;left++;}right++;}return max_window_length;}
};

两种解法性能相差挺大的。

下面一题和本题几乎一模一样,甚至是简化,我们也同样用两种思路来做吧。

1004. 最大连续1的个数 III

https://leetcode-cn.com/problems/max-consecutive-ones-iii/
给定一个由若干 0 和 1 组成的数组 A,我们最多可以将 K 个值从 0 变成 1 。

返回仅包含 1 的最长(连续)子数组的长度。
示例 1:

输入:A = [1,1,1,0,0,0,1,1,1,1,0], K = 2
输出:6
解释:
[1,1,1,0,0,1,1,1,1,1,1]
粗体数字从 0 翻转到 1,最长的子数组长度为 6。

示例2:

输入:A = [0,0,1,1,0,0,1,1,1,0,1,1,0,0,0,1,1,1,1], K = 3
输出:10
解释:
[0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1]
粗体数字从 0 翻转到 1,最长的子数组长度为 10。

友情提醒

由于这一题的简化性,最好好好看看两者代码有何区别,不然以为是一样的。(其实性能应该差不多,因为这里在找当前最大频数的时候不需要比较26次了,只需要一次。)

方法1,基于当前最大频数

class Solution {public:int longestOnes(vector<int>& A, int K) {int left = 0, right = 0;int one_times = 0;int now_max_freq = 0;int max_window_length = 0;while(right < A.size()){int c = A[right];if(c == 1) one_times++;if(one_times + K >= right - left + 1){max_window_length = max(max_window_length,right - left + 1);}else{int d = A[left];if(d == 1) one_times--;left++;}right++;}return max_window_length;}
};

方法2,基于历史最大频数

class Solution {public:int longestOnes(vector<int>& A, int K) {int left = 0, right = 0;int one_times = 0;int history_max_freq = 0;int max_window_length = 0;while(right < A.size()){int c = A[right];if(c == 1) one_times++;history_max_freq = max(history_max_freq,one_times);if(history_max_freq + K >= right - left + 1){max_window_length = max(max_window_length,right - left + 1);}else{int d = A[left];if(d == 1) one_times--;left++;}right++;}return max_window_length;}
};

leetcode 滑动窗口小结 (二)相关推荐

  1. leetcode 滑动窗口小结 (一)

    目录 小结以及代码框架 76. 最小覆盖子串 滑动窗口 代码以及注释 567. 字符串的排列 滑动窗口 438. 找到字符串中所有字母异位词 3. 无重复字符的最长子串 化简框架 reference ...

  2. leetcode 滑动窗口小结 (三)

    目录 978. 最长湍流子数组 题目 思路分析以及代码 1052. 爱生气的书店老板 题目 思考分析与初步代码 优化思路以及优化代码 1208. 尽可能使字符串相等 题目 思考分析以及代码 978. ...

  3. leetcode 滑动窗口1

    leetcode 滑动窗口1 leetcode159. 至多包含两个不同字符的最长子串 1. 题目 2. 解答 leetcode1151. 最少交换次数来组合所有的1 1. 题目 2. 解答 leet ...

  4. 【LeetCode笔记】剑指 Offer 57- II. 和为 s 的连续正数序列(Java、滑动窗口、二刷)

    文章目录 题目描述 思路 & 代码 二刷 题目描述 花了不少时间来优化= =,很好的一道用来理解滑动窗口的题- 思路 & 代码 要点:为了 O(n) 复杂度,左右边界都只能往右走 滑动 ...

  5. LeetCode 滑动窗口(Sliding Window)类问题总结

    导语 滑动窗口类问题是面试当中的高频题,问题本身其实并不复杂,但是实现起来细节思考非常的多,想着想着可能因为变量变化,指针移动等等问题,导致程序反复删来改去,有思路,但是程序写不出是这类问题最大的障碍 ...

  6. 5.18 优先队列(堆) 滑动窗口(二) 交换链表的节点

    295. 数据流的中位数 最简单的思路暴力法,每次读入数据都进行排序 但是中位数只对中间的一个或两个数据感兴趣,其他数没有必要进行交换或者比较 https://leetcode-cn.com/prob ...

  7. leetcode 滑动窗口—— 209/1456

    一.209长度最小的子数组 1.题目 https://leetcode-cn.com/problems/minimum-size-subarray-sum/ 给定一个含有 n 个正整数的数组和一个正整 ...

  8. 数据结构算法——滑动窗口问题(以LeetCode滑动窗口题为例)

    1. 滑动窗口 滑动窗口算法是在给定特定窗口大小的数组或字符串上执行要求的操作,它的原理与网络传输TCP协议中的滑动窗口协议(Sliding Window Protocol)基本一致. 这种技术可以将 ...

  9. leetcode 滑动窗口

    滑动窗口 文章目录 滑动窗口 模板框架 [76. 最小覆盖子串](https://leetcode-cn.com/problems/minimum-window-substring/) 思路分析 代码 ...

最新文章

  1. javascript-行间样式,提取行间事件,while/for,全选/反选/取消,选项卡,innerHTML
  2. 牛顿迭代法求解平方根
  3. 工作项跟踪管理系统需求
  4. android gif转jpg格式文件,android使用多张图片合成gif文件
  5. C++STL笔记(五):Deque详解
  6. 防备电脑死机故障技巧的8个方法
  7. Anaconda 安装步骤
  8. viper4android哪个版本好,ViPER4Android FX蝰蛇音效下载-ViPER4Android FX蝰蛇音效 v2.7.0.0_手机乐园...
  9. oracle12 client 64位,oracle官方64位客户端-instantclient-basic-windows.x64-12.2.0.1.0.zip
  10. SQL Server2000安装sp4补丁中的错误与破解
  11. ept技术_intel EPT 机制详解
  12. uniapp 评价应用_uniapp打开应用市场(APP端)
  13. 原来自动驾驶离不开OpenStack
  14. python成绩统计_Python编程语言:程序代码统计成绩
  15. 中科院大牛博士是如何进行文献检索和阅读的(好习惯受益终生)
  16. C#实现在CAD图纸中插入另一个DWG图块的代码
  17. Cufflinks的使用
  18. openwrt gdb gdbserver调试方法汇总
  19. 从50亿图文中提取中文跨模态新基准Zero,奇虎360全新预训练框架超越多项SOTA
  20. 国六OBD在线排放监测终端拆解成本分析,你是不是买贵了?

热门文章

  1. 教你玩转CSS 下拉菜单
  2. 《Bash 脚本教程》免费发布啦,开源!
  3. 计算机专业常用图论,同等学力申硕计算机专业--数学公式集合(新增学习笔记)...
  4. php post调用api,PHP(CURL)POST数据调用API简单示例
  5. Ajax应用查询员工信息
  6. Promise实战AJAX封装
  7. 谈一谈Http Request 与 Http Response
  8. jsp输出所有请求头的名称
  9. bootstrap源码之滚动监听组件scrollspy.js详解
  10. 谈谈一些有趣的CSS题目(十五)-- 谈谈 CSS 关键字 initial、inherit 和 unset