问题:
给你一个 m x n 的矩阵 matrix 和一个整数 k ,找出并返回矩阵内部矩形区域的不超过 k 的最大数值和。
题目数据保证总会存在一个数值和不超过 k 的矩形区域。
示例 1:
1 | 输入:matrix = [[1,0,1],[0,-2,3]], k = 2 |
示例 2:
1 | 输入:matrix = [[2,2,-1]], k = 3 |
提示:
m == matrix.length
n == matrix[i].length
1 <= m, n <= 100
-100 <= matrix[i][j] <= 100
-105 <= k <= 105
前置知识:二维前缀和
二维前缀和数组中的每一个格子记录的是「以当前位置为区域的右下角(区域左上角恒定为原数组的左上角)的区域和」
如果觉得不清晰,请将将 f[i][j] 理解成是以 (i, j) 为右下角,(0, 0) 为左上角的区域和。
因此当我们要求 (x1, y1) 作为左上角,(x2, y2) 作为右下角 的区域和的时候,可以直接利用前缀和数组快速求解:
1 | sum[x2][y2] - sum[x1 - 1][y2] - sum[x2][y1 - 1] + sum[x1 - 1][y1 - 1] |
代码如下:
1 | class NumMatrix { |
- 时间复杂度:预处理前缀和数组需要对原数组进行线性扫描,复杂度为 O(n * m),计算结果复杂度为 O(1)。整体复杂度为 O(n * m)
- 空间复杂度:O(n * m)
解题思路:
朴素二位前缀和:
搜索所有子矩阵需要枚举「矩形左上角」和「矩形右下角」,复杂度是 O(m^2 * n^2)。
1 | class Solution { |
- 时间复杂度:预处理前缀和数组复杂度为 O(m * n),查找答案的复杂度为 O(m^2 * n^2)。整体复杂度为 O(m^2 * n^2)
- 空间复杂度:O(m * n)O(m∗n)
优化:前缀+二分
1 | class Solution { |
- 时间复杂度:枚举上下边界复杂度为 O(m^2);枚举右边界为 O(n)O(n),使用 TreeSet(基于红黑树)存储和查找左边界复杂度为 O(log n)。整体复杂度为O(m^2∗nlogn)
- 空间复杂度:O(m * n)
参考:AC_OIer