目录
-
- 1. 二维前缀和的知识铺垫
- 2. 以nums[i][j]为中心计算区域大小.
- 3. dp数组与ret数组之间的逻辑关系.
- 4. 细节: 如果[i,j]为中心的数组越界了呢?
下面继续分享一道用前缀和思想解决的算法问题 -> 矩阵区域和
1. 二维前缀和的知识铺垫
实际上, 有一道十分类似的基础题 -> 二维前缀和
因为比较简单, 下面就简单的说两个关键点:
- 计算二位前缀和数组的公式推导: dp[i][j] = dp[i-1][j] + dp[i][j-1] + nums[i][j] - dp[i-1][j-1]
这个很简单, 实际上推导的是二维前缀和数组如何递推的, 在已知左边前缀和和上面前缀和前提下, 可以用橙色部分 + 蓝色部分 + 红色部分 - 橙色蓝色交叉的部分(这样也就决定了必须是从左向右推导, 从上到下推导的一个顺序). - 利用二位前缀和数组求指定区域和: ret = dp[x2, y2] - dp[x1-1, y2] - dp[x2, y1-1] + dp[x1-1][y1-1]
上面这个图说明了如何利用我们前面求好的二位前缀和数组来求任何一个特定矩形大小的所有元素之和. 具体就不说了, 黄色区域的元素之和 = 所有颜色之和(dp[x2, y2]) - 绿色区域 - 蓝色区域 + 绿色和蓝色区域重叠部分.
这其实就是[二位前缀和模板题]的解答关键. 当然, 仅仅这些是远远不够的, 这仅仅是这道题的铺垫.
2. 以nums[i][j]为中心计算区域大小.
我们这道题 -> 矩阵区域和实际上就是对上面做了一个简单的变形. 我们以示例1为例, 来简单说一下这个题目要求我们做啥?
这样的话一种方法肯定就是暴力求解了, 以[i,j]为中心, 挨个遍历周围的元素然后相加给到ret数组中的元素, 显然效率很低.
为了提高效率, 我们借用二维前缀和来提高效率.
3. dp数组与ret数组之间的逻辑关系.
我们预处理出一个二位前缀和数组来.
然后如何将ret数组与dp数组建立关系呢? 请看下图:
但是, 还需要注意一个细节 -> 就是越界问题.
4. 细节: 如果[i,j]为中心的数组越界了呢?
上面标题说的啥意思呢? 就是类似于下面这种情况:
因此, 我们在计算的时候要进行判断, 如果要访问的值越过了mat数组, 我们需要即使进行纠正!
好了, 说完了上面还有一个小难点就是因为有三个数组, 一个mat数组, 一个dp数组, 还一个ret数组, 在编码方面两个小难点: