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

90 阅读1分钟

题目:
给定一个二维矩阵 matrix,以下类型的多个请求:

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

实现 NumMatrix 类:

  • NumMatrix(int[][] matrix) 给定整数矩阵 matrix 进行初始化
  • int sumRegion(int row1, int col1, int row2, int col2) 返回 左上角 (row1, col1) 、右下角 (row2, col2) 所描述的子矩阵的元素 总和 。

解法:
方法一:二维前缀和
前缀和矩阵NumMatrix.PrefixSum[i][j] 保存 满足0 <= x <= i;0 <= y <= j的所有matrix[x][y]的和。
则前缀和矩阵的生成关系为:PrefixSum[i][j] = PrefixSum[i - 1][j] + PrefixSum[i][j - 1] - PrefixSum[i - 1][j - 1] + matrix[i][j]
矩阵区域和的计算关系为:
sum = PrefixSum[row2][col2] - PrefixSum[row2][col1] - PrefixSum[row1][col2] + PrefixSum[row1 - 1][col1 - 1]

type NumMatrix struct {
	PrefixSum [][]int
}

func Constructor(matrix [][]int) NumMatrix {
	n := len(matrix)
	m := len(matrix[0])
	nMatrix := NumMatrix{
		PrefixSum: make([][]int, n),
	}
	for i := 0; i < n; i ++ {
		nMatrix.PrefixSum[i] = make([]int, m)
		for j := 0; j < m; j ++ {
			up, left, pre := 0, 0, 0
			if i - 1 >= 0 && j - 1 >= 0 {
				pre = nMatrix.PrefixSum[i - 1][j - 1]
			}
			if i - 1 >= 0 {
				left = nMatrix.PrefixSum[i - 1][j]
			}
			if j - 1 >= 0 {
				up = nMatrix.PrefixSum[i][j - 1]
			}
			nMatrix.PrefixSum[i][j] = up + left + matrix[i][j] - pre
		}
	}
	fmt.Println(nMatrix.PrefixSum)
	return nMatrix
}


func (this *NumMatrix) SumRegion(row1 int, col1 int, row2 int, col2 int) int {
	// row1, col1 (point2) 矩形右下角
	// row2, col2 (point1) 矩形左上角
	up, left, pre := 0, 0, 0
	if row1 - 1 >= 0 && col1 - 1 >= 0 {
		pre = this.PrefixSum[row1 - 1][col1 - 1]
	}
	if col1 - 1 >= 0 {
		left = this.PrefixSum[row2][col1 - 1]
	}
	if row1 - 1 >= 0 {
		up = this.PrefixSum[row1 - 1][col2]
	}
	return this.PrefixSum[row2][col2] - up - left + pre

}

方法二:一维前缀和
假设m x n的矩阵,我们可以把矩阵看出m个一维数组,对每个一维数组用一维前缀和计算。
这种方式比较好理解,但是如果是频繁对区域进行+,-运算,则每次都要对m行进行O(1)操作,复杂度O(row2-row1)

type NumMatrix struct {
    Sum [][]int
    Matrix [][]int
}


func Constructor(matrix [][]int) NumMatrix {
    m, n := len(matrix), len(matrix[0])
    numMatrix := NumMatrix{make([][]int, m), matrix}
    sum := 0
    for i := range matrix {
        numMatrix.Sum[i] = make([]int, n)
        for j := range matrix[i] {
            sum = sum + matrix[i][j]
            numMatrix.Sum[i][j] = sum
        }
    }
    return numMatrix
}


func (this *NumMatrix) SumRegion(row1 int, col1 int, row2 int, col2 int) int {
    ans := 0
    for i := row1; i <= row2; i ++ {
        ans = ans + this.Sum[i][col2] - this.Sum[i][col1] +  this.Matrix[i][col1]
    }
    return ans
}