[LeetCode0303题区域和检索 - 数组不可变] | 刷题打卡

1,172 阅读3分钟

题目描述

这题是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循环求值,不会先去考虑时间空间限制和思考最优解,虽然我们经常会说又不是不能用,但是说归说,在实际操作中还是尽可能的去学习、去优化、多思考、多动手。练的多了再看到这种题就能对解法了然于心。

加油!好兄弟们!

我的LeetCode

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