前缀运算符和后缀运算符(前缀算术表达式)

「前缀和」指数组的某下标之前的所有数组元素和(包含其自身)。前缀和是一种重要的预处理,能够降低算法的时间复杂度。

举个真实场景,有一组数字为:
const nums = [1,2,3,4,5,6,7,8,9]
现在需求来了,想获取「i」到「j」元素相加的和,如何求值?
const sumRange = (i, j) => {    var sum = 0    for (let start = 0; i<j+1; i++){        sum += sums[i];    }    return sum}
很简单,直接遍历嘛,通过下标拿到值后,相加即可;每次计算都需要检索一次,时间复杂度很高,我们应当想办法减少检索的次数。
看下 LeetCode 入门题目:
题目:区域和检索 – 数组不可变
链接:https://leetcode-cn.com/problems/range-sum-query-immutable/
var NumArray = function (nums) {    const preSum = new Array(nums.length + 1)    preSum[0] = 0    for (let i = 0; i < nums.length; i++) {        preSum[i + 1] = preSum[i] + nums[i]    }    this.preSum = preSum};
NumArray.prototype.sumRange = function (left, right) { return this.preSum[right + 1] - this.preSum[left]};
第一次接触前缀和,一开始看的懵懵懂懂。看了一篇文章没看懂,然后又换另一个人文章看,在 leetcode 里看了三篇文章。终于有了眉目,前缀和的解法真不错呀。
如果我们能计算出数组在每个下标处的前缀和,那就可以降低每次调用 sumRange(i,j) 的时间复杂度。
具体的实现方法:想取「i」到「j」的和,需要存到另一个数组sums里,把「i」到「j」值相加,并且存进去,这样就有了一个「和」数组,当你想取「i」到「j」和时,就只需要用「和数组」的 sums[j + 1] – sums[i] 就行。
「前缀和」目的是新建一个数组 sums。把需要计算区间值的数组 nums,遍历它的 nums[i] + nums[i-1] 的值,存入数组 sums 中。
上例子:
const nums = [1,2,3,4,5,6,7,8,9]
计算前缀和后:
const sums = [0,1,3,6,10,15,21,28,36,45]
以后每次计算数值的时候,都操作的是 sums[j + 1] – sums[i]。
解决了每次求值都遍历的问题,其实前缀和经常用于对数组做预处理,在预处理阶段时间复杂度为O(n),空间复杂度为O(n),重要的是:后期的每次求值都是O(1)。

图片授权基于 www.pixabay.com 相关协议
其实前缀和经常用于对数组做预处理,将题目做等价转化成求 preSum 的问题

原创文章,作者:小道研究,如若转载,请注明出处:https://www.sudun.com/ask/34499.html

(0)
小道研究的头像小道研究
上一篇 2024年4月12日
下一篇 2024年4月12日

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注