【LeetCode】303.区域和检索 - 数组不可变

143 阅读2分钟

区域和检索 - 数组不可变

给定一个整数数组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]))

示例1

输入:
["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))

思路

  • 本题目是一个设计题,首先想到的是暴力解法,只需要按部就班就可以解决。每次都需要通过sumRange根据下标i和下标j计算该范围内的和。如解法一。
  • 除此之外,我们也可以进一步优化。在初始化的时候使用前缀和的方法减少调用sumRange的次数。假设数组nums的长度为n,创建长度为n+1的数组,当0<=i<=n时,有dp[i+1]=dp[i]+nums[i]。dp[i]表示nums从下标0到i-1的前缀合。此时有:
sumRange(i,j)=dp[j+1]-dp[i]

解法一

type NumArray struct { // 定义结构体对象
    nums []int
    m int
    n int
}


func Constructor(nums []int) NumArray { // 初始化对象
    this:=NumArray{}
    this.nums=nums
    this.m=0
    this.n=0
    return this
}


func (this *NumArray) SumRange(left int, right int) int { // 计算方法
    sum:=0
    for i:=left;i<=right;i++{
        sum+=this.nums[i]
    }
    return sum
}


/**
 * Your NumArray object will be instantiated and called as such:
 * obj := Constructor(nums);
 * param_1 := obj.SumRange(left,right);
 */

解法二

type NumArray struct {
    dp []int
}


func Constructor(nums []int) NumArray { // 在初始化的时候,计算前缀和,减少计算的次数
    array:=NumArray{}
    curDp:=make([]int,len(nums)+1)
    for i:=0;i<len(nums);i++{
        curDp[i+1]=curDp[i]+nums[i]
    }
    array.dp=curDp
    return array
}


func (this *NumArray) SumRange(left int, right int) int {
    return this.dp[right+1]-this.dp[left]
}


/**
 * Your NumArray object will be instantiated and called as such:
 * obj := Constructor(nums);
 * param_1 := obj.SumRange(left,right);
 */