前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >图解矩阵区域和

图解矩阵区域和

作者头像
兜兜转转
发布2023-03-08 13:22:25
3700
发布2023-03-08 13:22:25
举报
文章被收录于专栏:CodeTimeCodeTime

问题

给你一个 m * 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]]

题解

如果采用暴力法,每个格子直接计算,会发现存在大量的重复计算,可先构造一个矩阵dp,原矩阵是mat,dp[i,j]表示从矩阵左上角mat[0,0]到右下角mat[i,j]这个范围构成的矩阵所有元素之和。 该矩阵可看作是一个左上角是(0,0),右下角是(i,j)围成的矩形的面积,得到该矩阵后,就可以采用面积差来计算任意矩形的面积。 比如下图求左上角(2,1)和右下角(4,3)构成的蓝色部分,可通过由(0,0)到(4,3)的面积减去绿色部分(0,0)到(1,3),减去黄色部分(0,0)到(4,0),当然红色部分(0,0)到(1,0)是2个矩形相交的部分,会被减去2次,所以还得增加1次。而这几部分矩形都是从(0,0)作为左上角的,面积都是已知的存储在dp中。

.tg {border-collapse:collapse;border-spacing:0;} .tg td{font-family:Arial, sans-serif;font-size:14px;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:black;} .tg th{font-family:Arial, sans-serif;font-size:14px;font-weight:normal;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:black;} .tg .tg-yj5y{background-color:#efefef;border-color:inherit;text-align:center;vertical-align:top} .tg .tg-9wq8{border-color:inherit;text-align:center;vertical-align:middle} .tg .tg-vndr{background-color:red;border-color:inherit;text-align:center;vertical-align:middle} .tg .tg-kndx{background-color:#34ff34;border-color:inherit;text-align:center;vertical-align:top} .tg .tg-c3ow{border-color:inherit;text-align:center;vertical-align:top} .tg .tg-zk7v{background-color:#34ff34;border-color:inherit;text-align:center;vertical-align:middle} .tg .tg-lxrp{background-color:#f8ff00;border-color:inherit;text-align:center;vertical-align:middle} .tg .tg-eix7{background-color:#f8ff00;border-color:inherit;text-align:center;vertical-align:top} .tg .tg-usjd{background-color:#3531ff;color:#ffffff;border-color:inherit;text-align:center;vertical-align:top}

1(0,0)

2(0,1)

3(0,2)

4(0,3)

5(0,4)

6(1,0)

7(1,1)

8(1,2)

9(1,3)

0(1,4)

1(2,0)

2(2,1)

3(2,2)

4(2,3)

5(2,4)

6(3,0)

7(3,1)

8(3,2)

9(3,3)

0(3,4)

1(4,0)

2(4,1)

3(4,2)

4(4,3)

5(4,4)

用动态规划法求dp

每个dp都可以看作是上边的dp加上左边的dp,减去相交的部分,同时还要加上这个dp本身在矩阵中的值 dp[i][j]=mat[i][j]+dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1]

1(0,0)

2(0,1)

3(0,2)

4(1,0)

5(1,1)

6(1,2)

7(2,0)

8(2,1)

9(2,2)

我这里为了避免边界检查,将dp在原矩阵上扩展了一行和一列,待计算完毕后再恢复回来

123456789

r=len(mat)c=len(mat[0])dp=[[0 for _ in range(c+1)] for _ in range(r+1)]for i in range(1,r+1): for j in range(1,c+1): dp[i][j]=mat[i-1][j-1]+dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1]dp.pop(0)for d in dp: d.pop(0)

当然你也可以先特殊处理第一行和第一列,再执行同样的计算。

123456789

dp=[[0 for _ in range(c)] for _ in range(r)]dp[0][0] = mat[0][0]for j in range(1,c): #处理第一行 dp[0][j]=mat[0][j]+dp[0][j-1]for i in range(1,r): #处理第一列 dp[i][0]=mat[i][0]+dp[i-1][0]for i in range(1,r): for j in range(1,c): dp[i][j]=mat[i][j]+dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1]

根据dp求每个格子的值

以每个格子作为中心点,根据半径可求得矩形的左上角start和右下角end,根据这2个点就可以得到上面说的4个矩形的面积了,当然还需要作边界检查,还有只有当start点既不在第一行也不在第一列时才会产生2个需要减去的矩形,换句话说,当start点在第一行或者第一列时,只会产生一个矩形或者没有。只有当出现2个矩形的时候,才会出现相交,同时这个相交部分会被减去2次,所以还得增加1次相交部分。

1234567

res=[[0 for _ in range(c)] for _ in range(r)]for i in range(r): for j in range(c): start=(max(i-K,0),max(j-K,0)) end=(min(i+K,r-1),min(j+K,c-1)) res[i][j]=dp[end[0]][end[1]] - (0 if start[0]==0 else dp[start[0]-1][end[1]]) - (0 if start[1]==0 else dp[end[0]][start[1]-1])+ (0 if start[0]==0 or start[1]==0 else dp[start[0]-1][start[1]-1])return res

时间复杂度 O(MN)

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-03-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 问题
  • 题解
    • 用动态规划法求dp
      • 根据dp求每个格子的值
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档