每日算法刷题Day10 5.19:leetcode不定长滑动窗口求最长/最大4道题,结束定长滑动窗口,用时1h
不定长滑动窗口
不定长滑动窗口主要分为三类:求最长子数组,求最短子数组,以及求子数组个数。
- 注:滑动窗口相当于在维护一个队列。右指针的移动可以视作入队,左指针的移动可以视作出队。
滑动窗口【基础算法精讲 03】
求最长/最大
1.一般题目都有「至多」的要求。
2.核心:找窗口成立的条件
模版套路
1.套路
三步走:入窗口-出窗口-更新答案(窗口大小)
- 1.入窗口:下标为right的元素进入窗口,更新相关统计量。
- 2.出窗口:right进入,统计量更新,可能导致当前窗口不满足要求。根据条件用while循环让下标为left 的元素依次离开窗口,更新相关统计量,直至满足条件。
- 3.更新答案,窗口大小为right-left+1,
res=max(res,right-left+1)
c++:
class Solution {
public:int lengthOfLongestSubstring(string s) {int n = s.size();int res = 0;map<char, int> cnt;int left = 0;for (int right = 0; right < n; right++) {// 1.right入窗口,更新统计量++cnt[s[right]];// 2.不满足条件,left出窗口while (cnt[s[right]] > 1) {--cnt[s[left]];left++;}// 3.更新答案res = max(res, right - left + 1);}return res;}
};
2.题目描述
1.给定一个字符串 s
,请你找出其中不含有重复字符(窗口条件)的 最长 子串 的长度。
2.给你一个字符串 s
,请找出满足每个字符最多出现两次(窗口条件)的最长子字符串,并返回该子字符串的 最大 长度。
3.给你一个二进制数组 nums
,你需要从中删掉一个元素。请你在删掉元素的结果数组中,返回最长的且只包含 1(窗口条件) 的非空子数组的长度。
(题意转化为,不定长窗口最多只有1个0(窗口条件),求不定长窗口的最长长度-1(因为必须删除一个元素))
4.如果你可以将 s
的子字符串转化为它在 t
中对应的子字符串,则返回可以转化的最大长度,用于变更字符串的最大预算是 maxCost
。(窗口条件)
3.学习经验
1. 3.无重复字符的最长子串(中等)
3. 无重复字符的最长子串 - 力扣(LeetCode)
思想
1.给定一个字符串 s
,请你找出其中不含有重复字符的 最长子串 的长度。
2.不含有重复字符用map作为统计量来维护
代码
c++:
class Solution {
public:int lengthOfLongestSubstring(string s) {int n = s.size();int res = 0;map<char, int> cnt;int left = 0;for (int right = 0; right < n; right++) {// 1.right入窗口,更新统计量++cnt[s[right]];// 2.不满足条件,left出窗口while (cnt[s[right]] > 1) {--cnt[s[left]];left++;}// 3.更新答案res = max(res, right - left + 1);}return res;}
};
2. 3090.每个字符最多出现两次的最长子字符串(简单)
3090. 每个字符最多出现两次的最长子字符串 - 力扣(LeetCode)
思想
1.给你一个字符串 s
,请找出满足每个字符最多出现两次的最长子字符串,并返回该子字符串的 最大 长度。
2.条件变为每个字符最多出现两次,改变第1题的条件即可
代码
c++:
class Solution {
public:int maximumLengthSubstring(string s) {int n = s.size();int res = 0;map<char, int> cnt;int left = 0;for (int right = 0; right < n; ++right) {++cnt[s[right]];while (cnt[s[right]] > 2) {--cnt[s[left]];++left;}res = max(res, right - left + 1);}return res;}
};
3. 1493.删除一个元素以后全为1的最长子数组(中等,题意转换)
1493. 删掉一个元素以后全为 1 的最长子数组 - 力扣(LeetCode)
思想
1.给你一个二进制数组 nums
,你需要从中删掉一个元素。
请你在删掉元素的结果数组中,返回最长的且只包含 1 的非空子数组的长度。
2.题意转化为,不定长窗口最多只有1个0,求不定长窗口的最长长度-1(因为必须删除一个元素)
代码
c++:
class Solution {
public:int longestSubarray(vector<int>& nums) {int n = nums.size();int res = 0, cnt0 = 0;int left = 0;for (int right = 0; right < n; ++right) {if (nums[right] == 0)++cnt0;while (cnt0 > 1) {if (nums[left] == 0)--cnt0;++left;}res = max(res, right - left + 1 - 1); // 删除掉一个元素长度减1}return res;}
};
4. 1208.尽可能使字符串相等
1208. 尽可能使字符串相等 - 力扣(LeetCode)
思想
1.如果你可以将 s
的子字符串转化为它在 t
中对应的子字符串,则返回可以转化的最大长度,用于变更字符串的最大预算是 maxCost
。(窗口条件限制)
代码
c++:
class Solution {
public:int equalSubstring(string s, string t, int maxCost) {int n = s.size(), m = t.size();int res = 0;int cost = 0;int left = 0;for (int right = 0; right < n && right < m; ++right) {cost += abs(s[right] - t[right]);while (cost > maxCost) {cost -= abs(s[left] - t[left]);++left;}res = max(res, right - left + 1);}return res;}
};