问题描述
对于一个 m * n 的矩阵,每项元素为 0 或 1.
问题1
求该矩阵中的最大子矩阵,子矩阵可以为长方形,但是子矩阵内的各项元素均为 1。
解决1
针对这个问题,可以枚举子矩阵的左右边界,复杂度为 O(n^2)。针对该边界内的m行,从上到下扫一次,每行的和,如果为左右边界之差,那么该行的每项元素都为 1 。从上往下扫各行,求得最长连续地满足要求的行数。从而可以求得子矩阵的面积。
求特定边界内每行的面积,如何求?L[i][j] 为 A[i][0] ~ A[i][j] 的元素之和。根据 L[i][j] 就可以方便的求得 特定行的区间面积。比如求 A[i][k1] ~ A[i][k2] 的和,那么就是 L[i][k2] - L[i][k1-1]。
因此总体的复杂度为 O(n^2) * O(m) 即 O(m*n^2),其中 m为从上往下扫描的时间。
问题2
针对问题1,如果该子矩阵为正方形,如何求解?
解决2
设定一个辅助数组 C[i][j] 对应着一个数值对(l, h),其中 l 是指从 A[i][j] 开始往左,且包含 1,其最大长度; h 是指 从A[i][j] 开始往上,且包含 1,其最大长度。
p[i][j] 为以 A[i][j]元素为右下边界的最大正方形矩阵的长度。
于是 p[i+1][j+1] = min( p[i][j]+1, c[i+1][j+1].l , c[i+1][j+1].h)
时间复杂度为O(mn),空间复杂度为O(mn)。
解决。
PS 原题链接:Elements of Programming Interviews, P120