前缀和数组问题LeetCode304

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

请添加图片描述

1. 解题技巧:**前缀和数组**,这是一道标准的前缀和问题

2. 思路分析

   1. 若如下题解,效率很差,因为sumRange方法会被频繁调用,但是他的时间复杂度为O(N),N为nums数组的长度

      ```
      class NumArray {
      
          private int[] nums;
      
          public NumArray(int[] nums) {
              this.nums = nums;
          }
      
          public int sumRange(int left, int right) {
              int res = 0;
              for (int i = left; i <= right; i++) {
                  res += nums[i];
              }
              return res;
          }
      }
      ```

   2. 因此,我们采用前缀和的方式,将sumRange函数的时间复杂度降为O(1),即将循环从sumRange中移出

   3. 构造一个前缀和数组int[] preSum,长度为nums.length + 1,preSum[0] = 0, preSum[i] 表示 nums[0] 到 nums[i - 1]的累加和

   4. 因此若要计算[left, right]的累加和,即返回preSum[right + 1] (nums数组前right个的累加和) - preSum[left] (nums数组前left - 1 个的累加和)

   5.![请添加图片描述](https://img-blog.csdnimg.cn/9b24e81093a845d7a9ec0cb6037bd9a1.png)


3. 代码实现

   ```
   class NumArray {
       private int[] preSum;
       public NumArray(int[] nums) {
           preSum = new int[nums.length + 1];
           for (int i = 1; i < preSum.length; i++) {
               preSum[i] = preSum[i - 1] + nums[i - 1];
           }
       }
   
       public int sumRange(int left, int right) {
           return preSum[right + 1] - preSum[left];
       }
   }
   ```
  1. LeetCode304 二维区域和检索 - 矩阵不可变

请添加图片描述

1. 思路分析

   1. 使用前缀和数组的解题技巧

   2. 定义二维数组preSum = new int[matrix.length + 1] [matrix[0].length + 1],preSum[i] [j]存放matrix的子矩阵(0, 0, i - 1 , j - 1)的元素总和

      因此preSum[i] [j] = preSum[i -1] [j] + preSum[i] [j + 1] + matrix[i - 1] [j - 1] - preSum[i - 1] [j - 1]

      图示如下,注意紫色为蓝色 + 红色,

在这里插入图片描述

   3. 计算灰色矩阵的元素总和即为 preSum[row2+1] [col2+1] (灰蓝红紫) - preSum[row2] [col1 + 1] (蓝紫) - preSum[row1] [col2 + 1] (红紫) + preSum[row1] [col1] (紫)

请添加图片描述

2. 代码实现

   ```
   class NumMatrix {
       private int[][] preSum;
       public NumMatrix(int[][] matrix) {
           int m = matrix.length, n = matrix[0].length;
           if (m == 0 || n == 0) return;
           preSum = new int[m + 1][n + 1];
           for (int i = 1; i < m + 1; i++) {
               for (int j = 1; j < n + 1; j++) {
                   preSum[i][j] = preSum[i - 1][j] + preSum[i][j - 1] + matrix[i - 1][j - 1] - preSum[i - 1][j - 1];
               }
           }
       }
   
       public int sumRegion(int row1, int col1, int row2, int col2) {
           return preSum[row2 + 1][col2 + 1] - preSum[row1][col2 + 1] - preSum[row2 + 1][col1] + preSum[row1][col1];
       }
   }
   ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值