
public int minOperations(int[] nums, int x) {
int left = 0,right = 0,n=nums.length,sum1=0,sum=0,len=-1;
for(int i=0;i<n;i++){
sum1+=nums[i];
}
int target=sum1-x;
if(target<0){
return -1;
}
for(;right<n;right++) {
sum += nums[right];
while (sum > target) {
sum -= nums[left++];//记得++
}
if (sum == target) {
len = Math.max(len, right - left + 1);
}
}
if(len==-1)return -1;
else return n-len;
}
要解决"滑动窗口最大连续1的个数"问题,我们可以通过滑动窗口(双指针) 思路高效求解,核心是在遍历中维护一个包含不超过k个0的窗口,并记录窗口的最大长度。
问题分析
给定二进制数组 nums和整数 k,允许翻转最多k个0为1 ,求翻转后最长连续1的长度。等价于:找到一个子数组,其中0的数量≤k,且该子数组长度最大(因为翻转后0全变1,子数组长度即为连续1的长度)。
解题思路(滑动窗口)
用左右指针 维护一个动态窗口 [left, right],并统计窗口内0的数量 count:
-
右指针扩张 :遍历数组,右指针
right逐个向右移动,若遇到0则count加1(记录窗口内0的数量)。 -
左指针收缩 :当窗口内0的数量
count超过k时,右移左指针left,直到count ≤ k(过程中若左指针指向0,则count减1)。 -
更新最大长度 :每次窗口稳定后(即
count ≤ k时),计算当前窗口长度right - left + 1,并更新全局最大长度。
代码实现(Java)
public class Solution {
public int longestOnes(int[] nums, int k) {
int left = 0; // 左指针,窗口左边界
int count = 0; // 窗口内0的数量
int maxLen = 0; // 记录最大连续1的长度
for (int right = 0; right < nums.length; right++) { // 右指针遍历数组
if (nums[right] == 0) {
count++; // 遇到0,窗口内0的数量+1
}
// 若0的数量超过k,左指针收缩窗口,直到0的数量≤k
while (count > k) {
if (nums[left] == 0) {
count--; // 左指针指向0,移出窗口后0的数量-1
}
left++; // 左指针右移,缩小窗口
}
// 计算当前窗口长度,更新最大长度
maxLen = Math.max(maxLen, right - left + 1);
}
return maxLen;
}
}
代码解释
-
初始化变量 :
left为窗口左边界,count统计窗口内0的数量,maxLen记录最长有效子数组长度。 -
右指针遍历 :
right从0开始遍历数组,遇到0时count加1。 -
左指针收缩 :当
count > k时,循环右移left,若left指向0则count减1(因为该0被移出窗口),直到count ≤ k。 -
更新最大长度 :每次窗口调整后,计算当前窗口长度
right - left + 1,并与maxLen比较,保留更大值。
复杂度分析
-
时间复杂度:O(n),其中n为数组长度。左右指针各遍历数组一次,整体为线性时间。
-
空间复杂度:O(1),仅使用常数额外空间。
该方法通过滑动窗口动态维护有效区间,在一次遍历中完成所有操作,保证了效率与简洁性。