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

时间:2013-07-09 20:55:02

标签: algorithm

NxN矩阵中查找最大和子矩形可以使用2-d kadane算法在O(n^3)时间内完成,如其他帖子所述。但是,如果矩阵是稀疏的,特别是O(n)非零条目,那么O(n^3)时间是否会被打败?

如果有帮助,对于我感兴趣的当前应用程序,只需要一个解决方案,该解决方案假定矩阵的每一行和每列中至多有一个非零值。但是,在我未来的应用程序中,这个假设可能不合适(只是稀疏性会持续),无论如何,我的数学直觉是可能存在简单利用稀疏性的良好解决方案,并且不会进一步利用矩阵的事实。对角线和置换矩阵的乘积。

1 个答案:

答案 0 :(得分:10)

是的,可以做得更好。

首先,让我们考虑允许我们

的数据结构
  1. O(logn)时间
  2. 中更新基础1D数组的任何单个值
  3. O(1)时间
  4. 中查找数组的最大子数组的总和

    实际上,如下所示的平衡二叉树可以完成这项工作。树结构可以描述为:

    1. 树的每个叶节点都代表数组的每个元素。
    2. 如果内部节点涵盖范围[a, b],则其左子项涵盖范围[a, c],其右子覆盖范围[c + 1, b],其中c = floor((a + b) / 2))
    3. 根节点涵盖范围[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]
      
    4. 每个节点v附加4个字段(包括叶节点和内部节点):

      • S[v]v' s范围内所有值的总和
      • M[v]v'范围内的最大子阵列总和
      • L[v]:从v' s范围左侧开始的最大子数组的总和
      • R[v]:在v范围右侧结束的最大子数组的总和

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

      • 对于任何叶节点vS[v] = A[v]M[v] = L[v] = R[v] = max{0, A[v]}
      • 对于任何内部节点v及其子lr
        • 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]

      现在让我们讨论如何使用此数据结构查找最大矩形。如果我们将矩形的上行和下行固定为ij行,则问题将变为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)

相关问题