Range Sum Query系列(Immutable,Mutable,2D - Immutable)

Range Sum Query - Immutable

题目:难度(Easy)

Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive.
Example:
Given nums = [-2, 0, 3, -5, 2, -1]
sumRange(0, 2) -> 1
sumRange(2, 5) -> -1
sumRange(0, 5) -> -3
Note:
You may assume that the array does not change.
There are many calls to sumRange function.
Tags:Dynamic Programming

分析:

        要求:原数组不会改变,方法sumRange会被调用很多次,这就要求计算sumRange的时间复杂度要尽量低。设sum[i]表示数组前i个元素之和(含第i个元素),那么显然有sumRange(i, j) = sum[j] - sun[i-1],如果sum数组能提前计算好,那么计算sumRange(i, j)的时间复杂度就是O(1)。所以可以在初始化时即__init__里面就实现sum[ ]的计算,在sumRange里使用该sum。计算sum[ ]的时间复杂度是O(n) ,计算sumRange的时间复杂度是O(1)

代码实现:

class NumArray(object):
    def __init__(self, nums):
        """
        initialize your data structure here.
        :type nums: List[int]
        """
	#初始化
        self.nums = nums
        self.sum = []

        n = len(nums)
        if n > 0:
            self.sum.append(self.nums[0])
            for i in range(1, n):
                self.sum.append(self.sum[-1] + nums[i])

    def sumRange(self, i, j):
        """
        sum of elements nums[i..j], inclusive.
        :type i: int
        :type j: int
        :rtype: int
        """
        n = len(self.nums)
        if j<i or i<0 or j<0 or i>=n or j>=n:
            return 0
        if i==j:
            return self.nums[i]
        elif i==0:
            return self.sum[j]
        else:
            return self.sum[j] - self.sum[i-1]
        


# Your NumArray object will be instantiated and called as such:
# numArray = NumArray(nums)
# numArray.sumRange(0, 1)
# numArray.sumRange(1, 2)


Range Sum Query 2D- Immutable

题目:难度(Medium)

Given a 2D matrix matrix, find the sum of the elements inside the rectangle defined by its upper left corner (row1, col1) and lower right corner (row2, col2).


The above rectangle (with the red border) is defined by (row1, col1) = (2, 1) and (row2, col2) = (4, 3), which contains sum = 8.
Example:

Given 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
Note:

You may assume that the matrix does not change.
There are many calls to sumRegion function.
You may assume that row1 ≤ row2 and col1 ≤ col2.

Tags:Dynamic Programming

分析:

        要求:原矩阵不能被改变,sumRegion方法会被频繁调用,同样需要sumRegion实现的复杂度要尽量低。同Range Sum Query - Immutable一维情况一样,我们构造辅助数组存储一些sum和值,这里就需要构造二维辅助数组,行数列数与原数组相同,sums[i][j]表示从左上角(0,0)到右下角(i,j)构成的子矩阵的所有元素的和值(含matrix[i][j]与matrix[0][0]),那么由集合运算的“容斥原理”可知:sumRegion(row1, col1, row2, col2)=sums[row2][col2] - sums[row1-1][col2] - sums[row2][col1-1] + sums[row1-1][col1-1]。

        在初始化时即__init__里面就实现sums[ ]的计算,在sumRange里使用该sums。计算sum[ ]的时间复杂度是O(n^2) ,计算sumRange的时间复杂度是O(1)

代码实现:

class NumMatrix(object):
    def __init__(self, matrix):
        """
        initialize your data structure here.
        :type matrix: List[List[int]]
        """
        m = len(matrix)
        n = len(matrix[0]) if m else 0
        print m,n
        self.sums = [[0]*n for _ in range(m)]
        #计算sums辅助和值,横向滚动累加,然后纵向滚动累加
        tmp = 0
        for i in range(m):
            for j in range(n):
                tmp += matrix[i][j]
                self.sums[i][j] = tmp
            tmp = 0
            
        tmp = 0
        for j in range(n):
            for i in range(m):
                tmp += self.sums[i][j]
                self.sums[i][j] = tmp
            tmp = 0
        
        

    def sumRegion(self, row1, col1, row2, col2):
        """
        sum of elements matrix[(row1,col1)..(row2,col2)], inclusive.
        :type row1: int
        :type col1: int
        :type row2: int
        :type col2: int
        :rtype: int
        """
        if row1 == 0 and col1 == 0:
            return self.sums[row2][col2]
        elif row1 == 0:
            return self.sums[row2][col2]- self.sums[row2][col1-1]
        elif col1 == 0:
            return self.sums[row2][col2]- self.sums[row1-1][col2]
        else:
            return self.sums[row2][col2] - self.sums[row1-1][col2] - self.sums[row2][col1-1] + self.sums[row1-1][col1-1]
        


# Your NumMatrix object will be instantiated and called as such:
# numMatrix = NumMatrix(matrix)
# numMatrix.sumRegion(0, 1, 2, 3)
# numMatrix.sumRegion(1, 2, 3, 4)



Range Sum Query - Mutable

题目:难度(Medium)

Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive.
The update(i, val) function modifies nums by updating the element at index i to val.
Example:

Given nums = [1, 3, 5]
sumRange(0, 2) -> 9
update(1, 2)
sumRange(0, 2) -> 8
Note:

The array is only modifiable by the update function.
You may assume the number of calls to update and sumRange function is distributed evenly(均匀分布的).
Tags: Segment Tree , Binary Indexed Tree

分析:

        要求:原数组只能通过update方法改变,方法sumRange与方法update的调用次数是均匀分布的,即两个方法的调用次数一样的频繁。这里我们只用树状数组(Binary Indexed Tree / Fenwick Tree)来处理。关于树状数组的讲解,我觉得这一片博文讲的很好:http://blog.csdn.net/int64ago/article/details/7429868,至少我看这篇博文看懂了。使用树状数组,修改原数组中某个值或者求某个区间和的时间复杂度均是O(n) ,由于使用了一个辅助数组(树状数组)所以空间复杂度也是O(n)

代码实现:

class NumArray(object):
    def __init__(self, nums):
        """
        initialize your data structure here.
        :type nums: List[int]
        """
        self.nums = nums
        self.n = len(nums)
        self.treeSum = [0] * (self.n+1)#从1开始计数
        
        #初始化treeSum树状数组
        for i in range(1, self.n+1):
            self.add(i, nums[i-1])
         
    
    
    def lowbit(self, k):
        return k&(-k)
        
    #更新维护treeSum
    def add(self, k, val):
        while k <= self.n:
            self.treeSum[k] += val
            k += self.lowbit(k)
            
    #1->k的区间和
    def sum(self, i):
        k = i+1
        result = 0
        while k:
            result += self.treeSum[k]
            k -= self.lowbit(k)
        return result
    
    def update(self, i, val):
        """
        :type i: int
        :type val: int
        :rtype: int
        """
        self.add(i+1, val-self.nums[i])
        self.nums[i] = val#别忘了更新nums数组
        

    def sumRange(self, i, j):
        """
        sum of elements nums[i..j], inclusive.
        :type i: int
        :type j: int
        :rtype: int
        """
        if i == 0:
            return self.sum(j)
        else:
            return self.sum(j) - self.sum(i-1)
        


# Your NumArray object will be instantiated and called as such:
# numArray = NumArray(nums)
# numArray.sumRange(0, 1)
# numArray.update(1, 10)
# numArray.sumRange(1, 2)

参考:

         树状数组讲解:http://blog.csdn.net/int64ago/article/details/7429868

       http://bookshadow.com/weblog/2015/11/18/leetcode-range-sum-query-mutable/



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值