前缀和(preSum)算法

一维数组求区间和

 

preSum 方法能快速计算指定区间段 【i,j】的元素之和。它的计算方法是从左向右遍历数组,当遍历到数组的i位置时,preSum 表示 i 位置左边的元素之和。

 

 

 推导过程引用自:https://leetcode-cn.com/problems/range-sum-query-immutable/solution/jian-dan-wen-ti-xi-zhi-fen-xi-qian-tan-q-t2nz/

 

 

算法思路:

1.设原数组nums大小为N,定义一个大小为N+1的数组preum,preSum[i] 表示该元素左边所有元素之和(不包含 i 元素)。遍历原数组,利用 preSum[i + 1] = nums[i] + preSum[i]

   每次对nums数组的[0,j)范围求和,赋值给presum[i]。

2.利用  sum(i, j) = preSum[j + 1] - preSum[i] 快速求区间和。

 

定义N+1大小的presum数组是因为,可以方便地求区间和,不需要对i=0的特殊情况进行处理。

 

构造时时间复杂度和空间复杂度都是O(n),查询O(n)。

 

 


class NumArray {
public:
    vector<int> presum;
    NumArray(vector<int>& nums)
  {
        int N = size(nums);
        presum.resize(N+1);
        for(int i = 0;i<N;i++)
        {
            presum[i+1] = presum[i] +nums[i];
        }
    }
    
    int sumRange(int i, int j) {
        return presum[j+1] - presum[i];
    }
};

参考:https://leetcode-cn.com/problems/range-sum-query-immutable/solution/presum-qian-zhui-he-xiang-xi-jiang-jie-b-nh23/

 

二维矩阵版:

 

同样的思路,不同的是

1.presum数组的推导方式,利用:

  preSum[i+1][j+1preSum[i][j+1]+preSum[i+1][j]preSum[i][j]+matrix[i][j]

2.求任意子矩阵的和:

sum([row1,col1]~[row2,col2])  = preSum[row2+1][col2+1]−preSum[row2+1][col1]−preSum[row1][col2+1]+preSum[row1][col1]

同样利用了  加一  的方法避免对特殊情况进行处理。

posted @ 2021-03-02 09:49  助手的fork  阅读(2290)  评论(0编辑  收藏  举报