2021/5/30-31 刷题笔记区域和检索与前缀和方法

Posted 黑黑白白君

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021/5/30-31 刷题笔记区域和检索与前缀和方法相关的知识,希望对你有一定的参考价值。



区域和检索 - 数组不可变

编号303

【题目】

给定一个整数数组 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 <= 104
  • -105 <= nums[i] <= 105
  • 0 <= i <= j < nums.length
  • 最多调用 104 次 sumRange 方法

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/range-sum-query-immutable
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

【我的方法】

在初始化时用一个数组subsum存储前 i 个元素的和(不含i),则sum[i:j]=subsum[j+1]-subsum[i]。

class NumArray:

    def __init__(self, nums: List[int]):
        self.subsum=[0]
        pre=0
        for i in nums:
            pre+=i
            self.subsum.append(pre)


    def sumRange(self, left: int, right: int) -> int:
        return self.subsum[right+1]-self.subsum[left]


# Your NumArray object will be instantiated and called as such:
# obj = NumArray(nums)
# param_1 = obj.sumRange(left,right)

# 执行用时:72 ms, 在所有 Python3 提交中击败了67.15%的用户
# 内存消耗:18.1 MB, 在所有 Python3 提交中击败了38.73%的用户

前缀和方法整理

1、初始化时进行预处理:

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

2、预处理:

  • 如果可以在初始化的时候计算出数组 nums 在每个下标处的前缀和,即可满足每次调用 sumRange 的时间复杂度都是 O(1)。
  • 小技巧将前缀和数组的长度设为 n+1 的目的是为了方便计算,不需要对 i=0 的情况特殊处理。


二维区域和检索 - 矩阵不可变

编号304

这道题是「303. 区域和检索 - 数组不可变」的进阶,第 303 题是在一维数组中做区域和检索,这道题是在二维矩阵中做区域和检索。

【题目】

给定一个二维矩阵,计算其子矩形范围内元素的总和,该子矩阵的左上角为 (row1, col1) ,右下角为 (row2, col2) 。


示例:

给定 matrix = [ [3, 0, 1, 4, 2], [5, 6, 3, 2, 1], [1, 2, 0, 1, 5],[4, 1, 0, 1, 7], [1, 0, 3, 0, 5] ]

sumRegion(2, 1, 4, 3) -> 8
sumRegion(1, 1, 2, 2) -> 11
sumRegion(1, 2,2, 4) -> 12

提示:

  • 你可以假设矩阵不可变。
  • 会多次调用 sumRegion 方法。
  • 你可以假设 row1 ≤ row2 且 col1 ≤ col2 。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/range-sum-query-2d-immutable
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

【我的方法】

1、分解为四块,sum[row1,col1,row2,col2]=sum[0,0,row2,col2]-sum[0,0,row2,col1-1]-sum[0,0,row1-1,col2]+sum[0,0,row1-1,col1-1]

2、所以初始化时定义前缀和subsum[0,0,i,j],先通过一维算出第 i 行的前 j 个的和,再算出前 i 行前 j 行的和。

  • 注意:为了避免特殊情况的判断,所以subsum在最左边和最上面各多了一行/列。
class NumMatrix:

    def __init__(self, matrix: List[List[int]]):
        self.n=len(matrix)
        self.m=len(matrix[0])
        self.subsum=[[0 for i in range(self.m+1)] for j in range(self.n+1)]
        
        for i in range(1,self.n+1):
            self.subsum[i][1]=matrix[i-1][0]
            for j in range(1,self.m+1):
                self.subsum[i][j]=matrix[i-1][j-1]+self.subsum[i][j-1]
            if i>1:
                for j in range(1,self.m+1):
                    self.subsum[i][j]+=self.subsum[i-1][j]
        # print(self.subsum)
        
    def sumRegion(self, row1: int, col1: int, row2: int, col2: int) -> int:
        sum1=self.subsum[row2+1][col2+1]
        sum2=self.subsum[row2+1][col1]
        sum3=self.subsum[row1][col2+1]
        sum4=self.subsum[row1][col1]
        # print(sum1,sum2,sum3,sum4)
        return sum1+sum4-sum2-sum3

# Your NumMatrix object will be instantiated and called as such:
# obj = NumMatrix(matrix)
# param_1 = obj.sumRegion(row1,col1,row2,col2)

# 执行用时:300 ms, 在所有 Python3 提交中击败了24.62%的用户
# 内存消耗:24.1 MB, 在所有 Python3 提交中击败了5.01%的用户

以上是关于2021/5/30-31 刷题笔记区域和检索与前缀和方法的主要内容,如果未能解决你的问题,请参考以下文章

leetcode之前缀和刷题总结2

2021/6/3 刷题笔记连续数组与前缀和哈希表

2021/5/29 刷题笔记和为K的子数组与前缀和哈希表

Leetcode——区域和检索 - 数组不可变 / 二维区域和检索 - 矩阵不可变 (前缀和)

前缀异或he前缀和(区域检索)

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