链接:
链接: link
基本思想
当要解决的问题包含一段连续的子序列,可以考虑使用滑动窗口
int left = 0;
for(right=0; right<nums.size(); right++){
sum += nums[right];
while(满足或不满足条件){
sum -= nums[left];
left++; //左指针右移
//记录结果(或者下面)
}
//记录结果(或者上面)
}
长度最小的子数组
找到长度最小的连续子数组,满足sum >= target
例如:
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
思路:暴力双层for循环,会超时。考虑到求的是一段连续的子序列(窗口),直接套用滑动窗口模板
代码:
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int sum = 0;
int result = nums.size()+1;
int left = 0;
int right = 0;
for(right=0; right<nums.size(); right++){
sum += nums[right];
//当满足条件时,移动左指针
while(sum >= target){
result = min(result, right-left+1);
sum -= nums[left];
left++;
}
}
return result==nums.size()+1 ? 0:result;
}
};
无重复字串
描述及实例:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
思路:
代码:
class Solution {
public:
int lengthOfLongestSubstring(string s) {
unordered_map<char, int> mymap;
int result = 0;
if(s.size()<=1) return s.size();
int left = 0;
for(int i=0; i<s.size(); i++){
mymap[s[i]]++;
while(mymap[s[i]]>1){
mymap[s[left]]--;
left++;
}
result = max(result, i-left+1);
}
return result;
}
};
713. 乘积小于 K 的子数组
题目描述及实例:
输入:nums = [10,5,2,6], k = 100
输出:8
解释:8 个乘积小于 100 的子数组分别为:[10]、[5]、[2],、[6]、[10,5]、[5,2]、[2,6]、[5,2,6]。
需要注意的是 [10,5,2] 并不是乘积小于 100 的子数组。
思路:
代码:
class Solution {
public:
int numSubarrayProductLessThanK(vector<int>& nums, int k) {
if(k<=1) return 0;
int result = 0;
int mul = 1;
int left = 0;
for(int right=0; right<nums.size(); right++){
mul *= nums[right];
while(mul >= k){
mul /= nums[left++];
}
result += right - left + 1;
}
return result;
}
};
2958. 最多 K 个重复元素的最长子数组
题目描述及实例:
输入:nums = [1,2,3,1,2,3,1,2], k = 2
输出:6
解释:最长好子数组是 [1,2,3,1,2,3] ,值 1 ,2 和 3 在子数组中的频率都没有超过 k = 2 。[2,3,1,2,3,1] 和 [3,1,2,3,1,2] 也是好子数组。
最长好子数组的长度为 6 。
思路:
代码:
class Solution {
public:
int maxSubarrayLength(vector<int>& nums, int k) {
unordered_map<int, int> mymap;
int left = 0;
int len = nums.size();
int result = 0;
for(int right=0; right<len; right++){
mymap[nums[right]]++;
while(mymap[nums[right]] > k){
mymap[nums[left]]--;
left++;
}
result = max(result, right-left+1);
}
return result;
}
};
1658. 将 x 减到 0 的最小操作数
题目描述及示例
输入:nums = [1,1,4,2,3], x = 5
输出:2
解释:最佳解决方案是移除后两个元素,将 x 减到 0 。
思路:
代码:
class Solution {
public:
int minOperations(vector<int>& nums, int x) {
//确定target
int tar = 0;
int len = nums.size();
for(int i=0; i<len; i++){
tar += nums[i];
}
tar -= x;
//如果为负数,说明,减完都不满足;
//如果恰好为0,说明需要全部减完。
if(tar<0) return -1;
if(tar==0) return nums.size();
//滑动窗口
int left = 0;
int sum = 0;
int result = len+1;
for(int right=0; right<len; right++){
sum += nums[right];
while(sum > tar){
sum -= nums[left++];
}
if(sum == tar){
result = min(result, len-(right-left+1));
}
}
return result==len+1 ? -1:result;
}
};