Leetcode 303. 区域和检索 - 数组不可变,难度:Easy。
原题请戳这里。
题目描述
给定一个整数数组 nums,求出数组从索引 i 到 j(i ≤ j)范围内元素的总和,包含 i、j 两点。
实现 NumArray 类:
NumArray(int[] nums)使用数组nums初始化对象int sumRange(int i, int j)返回数组nums从索引i到j(i ≤ 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^50 <= i <= j < nums.length- 最多调用
10^4次sumRange方法
思路分析
通读题意,首先想到的肯定是循环暴力求解,看上去时间复杂度是o(n),但注意提示中最多调用10^4次sumRange方法,多次反复遍历计算,显然有可能会超时。
那么接下来优化点就可以放在消除反复从i到j范围内元素遍历的计算上。圈出关键词如何快速得到某个子数组的总和,这里就需要使用前缀和的技巧了。(关于前缀和,可以看下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 春招闯关活动」, 点击查看 活动详情