为了能让博客更灵动、更有趣,特在此设立了一个广告位~

[数组]算法学习技巧之数组前缀和

106次阅读
没有评论

共计 1738 个字符,预计需要花费 5 分钟才能阅读完成。

数组的前缀和技巧,是通过“空间换时间”的策略,它通过预先求得数组前 [x,y] 项 元素的和 并存入 arr[x,y] = sum

前缀和的数组,其每一项的值是 数组前 n 项 数据的和,比如第 n 项 preSum[n] = 前 n-1 所有项元素的和

这个方法针对 一些 要求数组某个区间的和的题目,会使得时间复杂度降为 O(1)。

先看一个题目:

给你一个矩阵 matrix,计算索引  left  和  right (包含  left  和  right)之间的  nums  元素的   ,其中  left <= right

如果,在没学过前缀和以前,可能的实现过程是这样的:

public int sumRange(int left, int right) {
		// 用 for 循环遍历求和
		int sum = 0;
		for (int i = left; i <= right; i++) {sum += nums[i];
		}
		return sum;
	}

此时要求得范围内 元素的和,时间复杂度为 O(n) 而且这个方法在使用频繁的情况下,效率更糟糕

一维的前缀和实现方法

/**
 * @param {number[]} nums
 */
var NumArray = function(nums) {if(nums.lengt === 0 && typeof nums === null) {return []
    }
    let preSum = new Array(nums.length + 1).fill(0)
    preSum[0] = 0
// 此处预先将和求得以后存入数组的每项
    for(let i =1;i < preSum.length; i++) {preSum[i] = preSum[i -1] + nums[i - 1]
    }
    this.preSum = preSum
};

/** 
 * @param {number} left 
 * @param {number} right
 * @return {number}
 */
NumArray.prototype.sumRange = function(left, right) {
// 直接计算 求得范围内 元素的和
    return this.preSum[right + 1] - this.preSum[left]
};

要搞明白这个前缀和,就从这段代码说起

let preSum = new Array(nums.length + 1).fill(0)
    preSum[0] = 0
// 此处预先将和求得以后存入数组的每项
    for(let i =1;i < preSum.length; i++) {preSum[i] = preSum[i -1] + nums[i - 1]
    }
    this.preSum = preSum
};

这段代码,首先初始化了一个一维的数组 它的长度是给定的数组的长度 +1

将它的第一个元素设置为 0,是便于后续的计算。

着重看一下 循环体的实现:

for(let i =1;i < preSum.length; i++) {
preSum[i] = preSum[i -1] + nums[i – 1]
}

这段代码,初始化一个循环变量 i,从 1 开始作为访问数组的索引,循环体:preSum[i] = preSum[i -1] + nums[i – 1] 表示,当前数组位置保存前一个数组位 + 给定的数组的当前位。实际上 设置 preSum[0] = 0,正是为了将给定数组的第一位的值存进去,后续的循环天然形成了一种:preSum 数组 保存的值永远是其前一项值 加上给定数组的最新的一项的值。

就好像是这样一个感受:给定数组在上面洒水,而我们的数组在下面接。所以我们的数组保存的值一直是滞后的,而给定数组的值永远是相比而言往前一项。那么,在每一次循环就是一次递增,每一项正好是前面的前面的和 + 前面的一项,所以当前项 preSum[n] 的值 就是前 n - 1 项 所有元素的和

注意点:

在了解前缀和的实现原理之后,对于使用它,是有一些局限的

  1. 使用前缀和,原给定数组的值 不应该发生变化,不然,我们已经计算过的和 都会失效。这样情况下,再重新计算和,则会花费更多的时间,失去了其存在的意义

用豆包的话说:前缀和数组是基于原数组的“累加结果”构建的,一旦原数组元素发生修改(如增、删、改),前缀和数组会产生“连锁反应”,导致更新效率极低。

2. 极端情况下,复杂度显著上升

当维度上升到二维,三维,这种用空间换时间的 技巧,其收益率大幅下降。因为需要维护前缀和数组,若原数组还需保留,那么空间需求更大

3. 该技巧只支持累加类的题目,除此之外 该技巧很可能失效。

正文完
文章二维码
post-qrcode
 0
xyblog
版权声明:本站原创文章,由 xyblog 于2025-10-29发表,共计1738字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)
这是全站底部广告位