You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

滑动窗口算法中windowStart自增时机及代码等价性疑问

最长连续1滑动窗口代码逻辑解析

原代码

public int longestOnes(int[] nums, int k) {
  int windowStart = 0, windowEnd;
  for (windowEnd = 0; windowEnd < nums.length; ++windowEnd) {
    if (nums[windowEnd] == 0) k--;
    if (k < 0 && nums[windowStart++] == 0) k++;
  }
  return windowEnd - windowStart;
}

原条件执行逻辑

if (k < 0 && nums[windowStart++] == 0) k++;的执行规则:

  • 逻辑与&&是短路求值:只有当k < 0为真时,才会执行后半段的判断和操作
  • 当k < 0时,先获取nums[windowStart]的值,立刻将windowStart自增1;如果这个值是0,就把k加1(相当于回收一次翻转0的名额)
  • 如果k >= 0,后半段代码完全不会执行,windowStart保持不变

简单说:只要窗口内的0数量超过k(k<0),就必须移动窗口左边界;如果移出的元素是0,就把可用的翻转名额加回来。

两段代码的核心差异

改写后的代码:

public int longestOnes(int[] nums, int k) {
  int windowStart = 0, windowEnd;
  for (windowEnd = 0; windowEnd < nums.length; ++windowEnd) {
    if (nums[windowEnd] == 0) k--;
    if (k < 0 && nums[windowStart] == 0) k++;
    if (k < 0) windowStart++;
  }
  return windowEnd - windowStart;
}

两者的关键区别在于窗口左边界移动的时机和条件:

  1. 原代码:只要k < 0,无论移出的元素是不是0,windowStart都会自增;只有当移出的是0时,才恢复k。这保证了窗口始终是当前能容纳最多1(含k个翻转0)的有效窗口,左边界只会单调右移。
  2. 改写后的代码:先判断当前左边界元素是不是0,是就恢复k,再看k是否还小于0才移动左边界。这会导致:如果移出的是0,k恢复后可能不再小于0,左边界就不移动——窗口会包含超过k个0,破坏了滑动窗口的有效性,最终计算出的窗口长度是错误的。

举个直观例子:nums = [0,0,1,1], k=1

  • 原代码执行到windowEnd=1时,k变为-1,触发条件:取nums[0](0),windowStart变为1,k恢复为0;最终返回4-1=3(正确,最多翻转1个0,最长连续1是3)
  • 改写后的代码执行到windowEnd=1时,k=-1:第一个判断恢复k为0,第三个判断k<0不成立,windowStart保持0;最终返回4-0=4(错误,此时窗口包含2个0,超过了k=1的限制)

内容的提问来源于stack exchange,提问作者Bardo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 22:27:20