【LeetCode刷题】Day 8
- 题目1:1004.最大连续1的个数 III
- 思路分析:
- 思路1:暴力枚举+zero计数器
- 思路2:滑动窗口+zero计数器
- 题目2:1658. 将x减到0的最小操作数
- 思路分析:
- 思路1:暴力枚举
- 思路2:滑动窗口O(N)
- 收获满满✨:
题目1:1004.最大连续1的个数 III
思路分析:
如果我们根据题干意思来做,每次寻找并翻转k个0的话,难度还是比较大,很复杂。我们不妨使用zero计数器来控制0的数量,控制在k以内。
思路1:暴力枚举+zero计数器
思路2:滑动窗口+zero计数器
-
本题滑动窗口分析:
-
1. 进窗口: 当
nums[right]!=0或者zero小于k
,就进窗口,执行right++
。意思就是right++就代表符合题意。 -
2. 判断: 主要目的是更新
left
到符合题干的位置,即: 减去一个零,使得zero计数器为k的位置。更新到位置也就完成了 出窗口。 -
3. 更新结果:
ret
是满足一个就更新一次,进窗口就是增加,出窗口就是减小(所以要和之前的比对,取最大)。
代码实现:
class Solution {
public:
int longestOnes(vector<int>& nums, int k) {
int left=0,right=0,n=nums.size();
int zero=0,ret=0;
while(right<n)
{
if(nums[right]==0) zero++; //zero计数器
while(zero>k) //出窗口
if(nums[left++]==0)
zero--;
ret=max(ret,right-left+1);//更新结果
right++; //符合要求进窗口-->right++;
}
return ret;
}
};
LeetCode链接:1004.最大连续1的个数
题目2:1658. 将x减到0的最小操作数
思路分析:
一会左删一会右删,让删除的总数等于x,这道题我们直接做会很难。
不妨正难则反:中间的部分的和一直是:sum-x
,要求删除最少,那就是中间长度最长。这样题目要求就变成了:找子数组的和等于target=sum-x
的最长子数组。
思路1:暴力枚举
思路2:滑动窗口O(N)
-
本题滑动窗口分析:
-
1. 进窗口: 维护数据
sum1
,right++
进窗口。 -
2. 判断: 如果
sum1>target
,则需要出窗口来减少sum1
。出窗口操作:sum1-=nums[left++];
-
3. 更新结果: 需要满足条件再更新结果:
if(sum1==target) ret=max(ret,right-left+1);
代码实现:
class Solution {
public:
int minOperations(vector<int>& nums, int x) {
int left=0,right=0,n=nums.size();
int sum=0,sum1=0,ret=-1;、
//求和
for(int i=0;i<n;i++)
sum += nums[i];
int target=sum-x;
//细节处理:
if(target<0) return -1;
while(right<n)
{
sum1+=nums[right]; //进窗口
while(sum1>target) //判断
sum1-=nums[left++]; //出窗口
if(sum1==target)
ret=max(ret,right-left+1); //更新结果
right++;
}
return (ret==-1?ret:n-ret);
}
};
LeetCode链接:1658. 将x减到0的最小操作数
收获满满✨:
- 正难则反,这个往往是最难的,需要多多体会。
- 体会进窗口和出窗口,理解方式多样。
懒猫配果汁,美好周末!🎈🎈周末快乐~