在NxN
矩阵中查找最大和子矩形可以使用2-d kadane算法在O(n^3)
时间内完成,如其他帖子所述。但是,如果矩阵是稀疏的,特别是O(n)
非零条目,那么O(n^3)
时间是否会被打败?
如果有帮助,对于我感兴趣的当前应用程序,只需要一个解决方案,该解决方案假定矩阵的每一行和每列中至多有一个非零值。但是,在我未来的应用程序中,这个假设可能不合适(只是稀疏性会持续),无论如何,我的数学直觉是可能存在简单利用稀疏性的良好解决方案,并且不会进一步利用矩阵的事实。对角线和置换矩阵的乘积。
答案 0 :(得分:10)
是的,可以做得更好。
首先,让我们考虑允许我们
的数据结构O(logn)
时间O(1)
时间实际上,如下所示的平衡二叉树可以完成这项工作。树结构可以描述为:
[a, b]
,则其左子项涵盖范围[a, c]
,其右子覆盖范围[c + 1, b]
,其中c = floor((a + b) / 2))
。 根节点涵盖范围[1, n]
。
O
/ \
/ \
/ \
/ \
/ \
O O
/ \ / \
/ \ / \
/ \ / \
O O O O
/ \ / \ / \ / \
o o o o o o o o
A[1] A[2] A[3] A[4] A[5] A[6] A[7] A[8]
每个节点v
附加4个字段(包括叶节点和内部节点):
S[v]
:v
' s范围内所有值的总和M[v]
:v
'范围内的最大子阵列总和L[v]
:从v
' s范围左侧开始的最大子数组的总和R[v]
:在v
范围右侧结束的最大子数组的总和根据以上定义,我们可能会发现以下更新规则:
v
,S[v] = A[v]
,M[v] = L[v] = R[v] = max{0, A[v]}
v
及其子l
和r
,S[v] = S[l] + S[r]
M[v] = max{M[l], M[r], R[l] + L[r]}
L[v] = max{L[l], L[r] + S[l]}
R[v] = max{R[r], R[l] + S[r]}
最后,我们可以实现开头提到的操作。
A[i]
,我们可能会在树中找到相应的叶节点,并使用上述规则更新其路径中的字段。 M[root]
。现在让我们讨论如何使用此数据结构查找最大矩形。如果我们将矩形的上行和下行固定为i
和j
行,则问题将变为1D最大子阵列求和问题,其中A[k] = sum{B[i..j, k]}
。关键的见解是,对于固定的i
,如果我们按升序枚举j
,我们可以使用上述数据结构来维护底层的1D数组并快速找到答案。伪代码描述了这个想法:
result = 0
for i in (1, 2, ..., n)
set all fields of the binary tree T to 0
for j in (i, i + 1, ..., n)
for any k where B[j, k] != 0
T.update(k, A[k] + B[j, k])
result = max{M[root], result}
return result
假设矩阵包含m
个非零元素,此算法的时间复杂度为O(mn logn)
。在您的情况m = O(n)
中,时间复杂度为O(n^2 logn)
且优于O(n^3)
。