题目

给定一个整数数组 nums,计算出从第 i 个元素到第 j 个元素的和 ( i ≤ j ),包括 nums[i] 和 nums[j]。

例子:

1
2
3
4
const arr = Object.freeze([1, 2, 3, 4, 5, 6])
sumRange(0, 2) // 6
sumRange(2, 5) // 18
sumRange(0, 5) // 21

注意:

1、数组的值不会改变
2、sumRange 可能会被使用很多次,求不同范围的值
3、数组可能规模很大(比如超过 10000 个数),注意运行时间

简单实现

1
2
3
4
5
6
7
function sumRange(i, j){
let sum = 0;
for(; i <= j; i++){
sum += arr[i];
}
return sum;
}

考虑到注意事项中的2、3,简单实现的代码是非常慢的,在数组非常大时,可能会导致程序超时。

查表方法

二维表可以将每一对 i, j 完全映射一个值,空间复杂度为 O( n2),但是在数组非常大时,二维映射表就可能内存溢出了。

1
2
3
4
5
6
7
//    0  1  2  3  4   5
// 0 1 3 6 10 15 21
// 1 2 5 9 14 20
// 2 3 7 12 18
// 3 4 9 15
// 4 5 11
// 5 6

由于数组在初始化后值不会再改变,这里可以发现一个规律。

sumRange(i, j) === sumRange(0, j) - sumRange(0, i - 1);

下面是代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function sumConstructor(arr) {
this.sums = [];
this.arr = arr;
}

sumConstructor.prototype.sumRange = function (i, j) {
const { arr, sums } = this;
const lastIndex = arr.length - 1;
if (i < 0) i = 0;
if (j < 0) j = 0;
if (i > lastIndex) i = lastIndex;
if (j > lastIndex) j = lastIndex;
if (!sums.length) {
this.sums.push(0);
let sum = 0;
for (let i = 0; i < arr.length; i++) {
sum += arr[i];
this.sums.push(sum);
}
}
return this.sums[j + 1] - this.sums[i];
}

const arr = Object.freeze([1, 2, 3, 4, 5, 6]);

const sum = new sumConstructor(arr);

console.log(sum.sumRange(0, 2))
console.log(sum.sumRange(0, 6))