Skip to content
本页目录

1314-矩阵区域和

https://leetcode.cn/problems/matrix-block-sum

给你一个 m x n 的矩阵 mat 和一个整数 k ,请你返回一个矩阵 answer ,其中每个 answer[i][j] 是所有满足下述条件的元素 mat[r][c] 的和:

i - k <= r <= i + k,
j - k <= c <= j + k 且
(r, c) 在矩阵内。

示例 1:

输入:mat = [[1,2,3],[4,5,6],[7,8,9]], k = 1
输出:[[12,21,16],[27,45,33],[24,39,28]]

示例 2:

输入:mat = [[1,2,3],[4,5,6],[7,8,9]], k = 2
输出:[[45,45,45],[45,45,45],[45,45,45]]

提示:

m == mat.length
n == mat[i].length
1 <= m, n, k <= 100
1 <= mat[i][j] <= 100

基本思路 暴力解法

注意读懂题目, 目标矩阵 r,c 处的值,就是原来的矩阵处 mat[r][c] 的值,周围扩散 k 所有值的和。 先试一下暴力法,直接遍历,遍历到目标数组再循环周围的值相加,可能会超时(暴力法通过了)

参考代码

csharp
public class Solution {

	protected int CalcSum(int[][] mat, int i, int j, int k){
		int sum = 0;
		for(int ii=i-k;ii<=i+k;ii++){
			for(int jj = j-k; jj<=j+k;jj++){
				//判断越界
				if(ii>=0 && jj>=0 && ii<mat.Length && jj<mat[0].Length){
					sum+=mat[ii][jj];
				}
			}
		}
		return sum;
	}

    public int[][] MatrixBlockSum(int[][] mat, int k) {
    	//初始化目标数组
    	int[][] answer = new int[mat.Length][];
    	for(int i=0;i<mat.Length;i++){
    		answer[i] = new int[mat[0].Length];
    	}
    	//计算和
    	for(int i=0;i<mat.Length;i++){
    		for(int j=0; j<mat[i].Length; j++){
    			answer[i][j] = CalcSum(mat,i,j,k);
    		}
    	}
    	return answer;
    }
}

基本思路2: 【官方解法】 知识点 矩阵前缀和

dp[i+1][j+1] = dp[i][j+1] + dp[i+1][j] - dp[i][j] + mat[i][j]

扩展矩阵为 m+1,n+1, dp[i,j] = 表示从目前矩阵中到[i,j]所有数字的和

注意边界 dp[i+1][j+1] 表示 mat[i,j] 的前缀和, 在最后扣减前面前缀和的时候是扣减 mat[i-1][j-1] 所以最后代码中 左上边界,x1,x2直接使用,不需要+1,因为需要扣减1的 这个数组多扩展1圈的方法很好用。

csharp
public class Solution{
	public int[][] MatrixBlockSum(int[][] mat, int k){
		//初始化dp, 注意dp要扩展1个单位
    	int[][] dp = new int[mat.Length+1][];
    	int[][] answer = new int[mat.Length][];
    	for(int i=0;i<mat.Length+1;i++){
    		dp[i] = new int[mat[0].Length+1];
            if(i<mat.Length){
                answer[i] = new int[mat[0].Length];
            }
    	}
    	//计算数组前缀和
    	for(int i=0;i<mat.Length;i++){
    		for(int j=0;j<mat[0].Length;j++){
                //Console.WriteLine("i={0},j={1}",i,j);
    			dp[i+1][j+1] = dp[i][j+1] + dp[i+1][j] - dp[i][j] + mat[i][j];
    		}
    	}
    	//计算矩阵区域和(注意dp对应关系是+1)
    	for(int i=0;i<mat.Length;i++){
    		for(int j=0;j<mat[0].Length;j++){
    			int x1 = Math.Max(0,i-k);
    			int y1 = Math.Max(0,j-k);
    			int x2 = Math.Min(mat.Length-1,i+k);
    			int y2 = Math.Min(mat[0].Length-1,j+k);
    			//区域和 = 最终区域和 - 上面前缀和 - 左边前缀和 + 左上前缀和(注意左边和上边的边界不包含)
    			answer[i][j] = dp[x2+1][y2+1] - dp[x1][y2+1] - dp[x2+1][y1] + dp[x1][y1];
    		}
    	}
    	return answer;
	}
}

Released under the MIT License.