前缀和|刷题打卡

146 阅读2分钟

Leetcode 303. 区域和检索 - 数组不可变,难度:Easy
原题请戳这里

题目描述

给定一个整数数组 nums,求出数组从索引 iji ≤ j)范围内元素的总和,包含 i、j 两点。
实现 NumArray 类:

  • NumArray(int[] nums) 使用数组 nums 初始化对象
  • int sumRange(int i, int j) 返回数组 nums 从索引 i 到 ji ≤ j)范围内元素的总和,包含 i、j 两点(也就是 sum(nums[i], nums[i + 1], ... , nums[j])

示例:

输入:
["NumArray", "sumRange", "sumRange", "sumRange"]
[[[-2, 0, 3, -5, 2, -1]], [0, 2], [2, 5], [0, 5]]
输出:
[null, 1, -1, -3]

解释:
NumArray numArray = new NumArray([-2, 0, 3, -5, 2, -1]);
numArray.sumRange(0, 2); // return 1 ((-2) + 0 + 3)
numArray.sumRange(2, 5); // return -1 (3 + (-5) + 2 + (-1)) 
numArray.sumRange(0, 5); // return -3 ((-2) + 0 + 3 + (-5) + 2 + (-1))

提示:

  • 0 <= nums.length <= 10^4
  • -10^5 <= nums[i] <= 10^5
  • 0 <= i <= j < nums.length
  • 最多调用 10^4sumRange 方法

思路分析

通读题意,首先想到的肯定是循环暴力求解,看上去时间复杂度是o(n),但注意提示中最多调用10^4sumRange方法,多次反复遍历计算,显然有可能会超时。
那么接下来优化点就可以放在消除反复从ij范围内元素遍历的计算上。圈出关键词如何快速得到某个子数组的总和,这里就需要使用前缀和的技巧了。(关于前缀和,可以看下labuladong的总结之小而美的算法技巧
具体前缀和的做法就不赘述,大家可以自行去看上面的链接,另外LeetCode上@负雪明烛的题解中的动画也演示得非常清晰了。
话不多说,直接动手:

  • 需要开辟一个前缀和数组preSum[],用于存储前缀和,长度为nums.length + 1
  • 给前缀和数组第0位或所有位填上0进行初始化
  • 遍历原数组nums[]preSum[i + 1] = preSum[i] + nums[i] (体会下前缀和的含义)
  • 生成前缀和数组preSum[]后,需要求原数组中[i,j]范围内元素的总和,即是求preSum[j + 1] - preSum[i]

AC代码

/**
 * @param {number[]} nums
 */
var NumArray = function(nums) {
    let length = nums.length;
    this.sum = new Array(length + 1).fill(0);
    for(let i = 0; i < length; i++) {
        this.sum[i + 1] = this.sum[i] + nums[i];
    }
};

/** 
 * @param {number} i 
 * @param {number} j
 * @return {number}
 */
NumArray.prototype.sumRange = function(i, j) {
    return this.sum[j + 1] - this.sum[i];
};

/**
 * Your NumArray object will be instantiated and called as such:
 * var obj = new NumArray(nums)
 * var param_1 = obj.sumRange(i,j)
 */

总结

本题相似题目:

用到的js语言技巧

  • Array.fill(value, start, end),ES6增加方法,取值[start, end)可以省略,本质是使用value初始化数组的作用
  • js如何创建类,本题中示范的是使用混合构造函数和原型来创建一个类,此知识点可顺带复习红宝书第四版8.4章:类
  • this指向全局,可顺带复习你不知道的JavaScript(上卷)第二章

本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情