题目描述
这题是LeetCode0303题区域和检索 - 数组不可变,也是今天的每日一题。
给定一个整数数组 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
- -105 <= nums[i] <= 10^5
- 0 <= i <= j < nums.length
- 最多调用 104 次 sumRange 方法
解题思路
这道题给了一个数组,要我们实现返回给定的两个数组下标之前的元素和,要包含两个给定的数组下标元素,很简单啊,我看完第一遍就想到了最笨的方法,直接上来就是for循环,很快就写出来了,年轻人不讲5的,我自己都感觉自己6的一批,直接就点击提交,上来就是一个超出时间限制。这种方法如果说需要循环的数量少的话是没问题的,简单易懂。但是遇见数量多的情况时间复杂度就高了,就会出现这种超出时间限制的情况,所以这种方法不可取。
直接循环不可行怎么办呢?题目要求的是求出数组num给定索引下标的元素之间的和,那我们可以提前求出数组num在每个下标的前缀和不就行了。先设一个给定数组长度+1的新数组sum全部填充0(数组长度设为num的长度+1可以不需要考虑),索引i的前缀和为sum[i+1] = sum[i] + num[i],这样就可以实现题目要求的NumArray类了。
因为初始化需要遍历num,所以时间复杂度为O(n),空间复杂度也是O(n)。
解题代码
/**
* @param {number[]} nums
*/
var NumArray = function(nums) {
const n = nums.length;
this.sum = new Array(n + 1).fill(0);
for (let i = 0; i < n; 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];
};
总结
像我这种基础差的看到这种题很容易像我上面说的那样,上来就是for循环求值,不会先去考虑时间空间限制和思考最优解,虽然我们经常会说又不是不能用,但是说归说,在实际操作中还是尽可能的去学习、去优化、多思考、多动手。练的多了再看到这种题就能对解法了然于心。
加油!好兄弟们!
本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情