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

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

【LeetCode刷题-前缀和】--303.区域和检索-数组不可变_第1张图片

方法:前缀和

存储数组nums的值,每次调用sumRange时,通过循环的方法计算数组nums从下标i到下标j范围内的元素和,需要计算j-i+1个元素的和,由于每次检索的时间和检索的下标范围有关,因此检索的时间复杂度较高,如果检索次数较多,则会超出时间限制。

由于会进行多次检索,即每次调用sumRange,因此为了降低检索的总时间,应该降低sumRange的时间复杂度,最理想的情况是时间复杂度O(1),为了将检索的时间复杂度降到O(1),需要在初始化的时候进行预处理。

【LeetCode刷题-前缀和】--303.区域和检索-数组不可变_第2张图片

由此可知,要计算sumRange(i,j),则需要计算数组nums在下标j和下标i-1的前缀和,然后计算两个前缀和的差。

如果可以在初始化的时候计算出数组nums在每个下标处的前缀和,即可满足每次调用sumRange的时间复杂度都是O(1)

具体实现:

假设数组nums的长度为n,创建长度为n+1的前缀和和数组nums,对于0≤i<n都有sums[i+1]=sums[i]+nums[i],则当0<i≤n时,sums[i]表示数组nums从下标0到下标i-1的前缀和

将前缀和数组sums的长度设为n+1的目的是为了方便计算sumRange(i,j),不需要对i=0的情况特殊处理,此时有:

sumRange(i,j)=sums[j+1]-sums[i]

class NumArray {
    int[] sums;

    public NumArray(int[] nums) {
        int n = nums.length;
        sums = new int[n+1];
        for(int i = 0;i < n; i++){
            sums[i + 1] = sums[i] + nums[i];
        }
    }
    
    public int sumRange(int left, int right) {
        return sums[right + 1] - sums[left];
    }
}

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

你可能感兴趣的:(LeetCode,leetcode,算法)