稀疏矩阵中的最大和子矩形

Posted

技术标签:

【中文标题】稀疏矩阵中的最大和子矩形【英文标题】:maximum sum subrectangle in a sparse matrix 【发布时间】:2013-07-09 20:55:02 【问题描述】:

正如其他帖子中所指出的,可以使用二维 kadane 算法在 O(n^3) 时间内在 NxN 矩阵中找到最大和子矩形。但是,如果矩阵是稀疏的,特别是 O(n) 非零条目,那么 O(n^3) 时间可以被打败吗?

如果它有帮助,对于我感兴趣的当前应用程序,有一个解决方案就足够了,假设矩阵的每一行和每一列中最多有一个非零值。然而,在我未来的应用程序中,这个假设可能不合适(只是稀疏性会成立),无论如何我的数学直觉是,可能有很好的解决方案可以简单地利用稀疏性而不进一步利用矩阵是对角线和置换矩阵的乘积。

【问题讨论】:

如果每行和每列最多有非零值,然后将这些值投影到x轴和y轴上,您将得到两个一维数组大小 n。找到两个数组的最大连续子数组。我认为这会给你最大的子矩形。这可以在 O(n) 时间和 O(n) 空间复杂度内完成。 不幸的是,这个提议的 O(n) 解决方案不起作用,如以下反例所示:1 0 0\\ 0 0 2\\ 0 -1 0\\ 【参考方案1】:

是的,可以做得更好。

首先,让我们考虑一个数据结构,它允许我们

    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范围内所有值的总和 M[v]v 范围内的最大子数组和 L[v]:从v的范围左侧开始的最大子数组的总和 R[v]:在v的范围右侧结束的最大子数组的总和

根据以上定义,我们可以发现以下更新规则:

对于任何叶节点vS[v] = A[v]M[v] = L[v] = R[v] = max0, A[v] 对于任何内部节点v 及其子节点lrS[v] = S[l] + S[r] M[v] = maxM[l], M[r], R[l] + L[r] L[v] = maxL[l], L[r] + S[l] R[v] = maxR[r], R[l] + S[r]

最后,我们可以实现开头提到的操作了。

要更新A[i],我们可以在树中找到对应的叶节点,并使用上述规则将沿其路径的字段更新到根。 最大子数组和就是M[root]

现在让我们讨论如何使用此数据结构找到最大矩形。如果我们将矩形的上一行和下一行固定为ith 和jth 行,则问题变成一维最大子数组和问题,其中A[k] = sumB[i..j, k]。关键的见解是,对于一个固定的i,如果我们按升序枚举j,我们可以使用上面的数据结构来维护底层的一维数组并很​​快找到答案。伪代码描述了这个想法:

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 = maxM[root], result
return result

假设矩阵包含m非零元素,该算法的时间复杂度为O(mn logn)。在你的情况下m = O(n),所以时间复杂度是O(n^2 logn),比O(n^3)好。

【讨论】:

谢谢,这个答案看起来是正确的,改进将有助于大 n。我浏览了文献和在线,对于稀疏矩阵的这个问题,我没有发现比 O(n^3) 更好的东西。因此,我们将不得不在我们关于辐射源检测的应用论文中描述这个算法,因为我们的听众想知道我们使用什么算法。请让我知道您是否打算为此写一个简短的注释以供出版,如果是,请告诉我作者/工作名称,以便我们可以为您提供应有的引用。或者,如果您只是想要一个确认,我们也可以这样做。 如果可能的话,我只想致谢。您可以在我的个人资料中找到我的电子邮件。但是,我发现这个页面描述了类似的想法:wcipeg.com/wiki/…

以上是关于稀疏矩阵中的最大和子矩形的主要内容,如果未能解决你的问题,请参考以下文章

稀疏矩阵及其压缩格式

来自密集的Tensorflow的稀疏矩阵

具有特征库的块稀疏矩阵

以对数方式缩放(应用函数?)稀疏矩阵

如何写成高性能的代码:巧用稀疏矩阵节省内存占用

如何写成高性能的代码:巧用稀疏矩阵节省内存占用