JavaScript数组最大连续k项和函数末尾减法操作逻辑疑问
关于滑动窗口求和代码的疑问解答
你提到的temp_sum -= nums[i - k + 1]是滑动窗口算法中更新窗口和的核心步骤,我们可以拆成3个问题逐一解释:
1. 这行代码的作用是什么?
连续k个元素的窗口每次向右滑动1位时,和上一个窗口相比,只有最左侧的元素被移出窗口、最右侧新增一个元素,不用重新累加k个元素的值,只需要:
- 加上新进入窗口的右侧元素
- 减去被移出窗口的左侧元素(就是这行代码做的事)
就能快速得到新窗口的和,把时间复杂度从暴力解法的O(n*k)降到O(n)。
2. 具体要减去哪个值?
我们用你给出的测试用例nums = [1,2,3,14,5],k=3来举例:
- 当窗口右边界下标
i=2时,当前窗口是[1,2,3],被移出的左边界元素是nums[0] = 1,代入公式i -k +1 = 2-3+1=0,刚好对应下标0的元素 - 当窗口右边界下标
i=3时,当前窗口是[2,3,14],被移出的左边界元素是nums[1] = 2,代入公式3-3+1=1,刚好对应下标1的元素
所以这行代码减去的就是上一个窗口最左侧、本次滑动后不再属于窗口的元素值。
3. 为什么公式里要用到数值1?
因为数组的下标是从0开始计数的。
假设窗口右边界下标为i,窗口长度为k,如果不加1的话左边界就是i-k,拿上面的例子i=2、k=3代入会得到-1,是非法的下标。加1之后刚好能对齐0起始的下标规则,算出的左边界永远是窗口第一个元素的正确下标。
额外提示:你贴出的代码存在逻辑错误
两层循环都用var声明变量i会导致变量提升,i的值会被内层循环覆盖,且内层循环不该嵌套在外层循环中,修正后的正确实现参考:
function array_max_consecutive_sum(nums, k) { // 边界处理:k超过数组长度直接返回0 if (k > nums.length) return 0 let result = 0 let temp_sum = 0 // 先算第一个窗口的和 for (let i = 0; i < k; i++) { temp_sum += nums[i] } result = temp_sum // 滑动窗口遍历剩余元素 for (let i = k; i < nums.length; i++) { // 加新进入窗口的右侧元素,减移出窗口的左侧元素 temp_sum += nums[i] temp_sum -= nums[i - k] // 更新最大值 if (temp_sum > result) { result = temp_sum } } return result } console.log(array_max_consecutive_sum([1, 2, 3, 14, 5], 3)) // 输出22
内容的提问来源于stack exchange,提问作者Piotrek Krakowiak
相关产品推荐
相关产品推荐

