【问题标题】:Maximum size submatrix with same integers具有相同整数的最大大小子矩阵
【发布时间】:2015-03-02 23:18:38
【问题描述】:

有一个 MxN 大小的矩阵,其中包含整数。我们需要找到其中具有相同整数的最大尺寸子矩阵。例如:

1 2 2 4 5
1 2 2 8 7
3 2 2 6 1

这里最大的子矩阵是 3x2 大小,其中包含所有 2。我的想法是检查每个元素 arr[i][j] ,是否 arr[i][j+1] , arr[i+1]arr[j+1] 和 arr[i+1][j]相等或不相等。如果它们相等,那么我们可以以某种方式更新矩阵的最大大小。但我无法得出确切的解决方案。

我想知道我们是否可以以某种方式利用动态编程。这是一道面试题。

【问题讨论】:

  • 阅读此内容:geeksforgeeks.org/… 只需简单更改您的 DP 算法 :)
  • @AliAmiri 这个比较难,因为这里的子矩阵不需要是正方形的。
  • @ILoveCoding 我知道这个比较难,但我认为同样的想法会有所帮助(目前我在工作,回家后我会考虑解决方案)

标签: algorithm matrix language-agnostic dynamic-programming


【解决方案1】:
  1. 假设子矩阵的底行是固定的。然后每一列可以表示为一对(值,高度),其中值是该行和列中元素的值,高度是该列中与它相等的连续元素的数量。例如,如果矩阵是

    3 1 2 3 
    1 2 2 1
    3 2 2 1
    2 2 2 2
    

    我们正在查看的底行是 2(在从零开始的索引中),值分别是 (3, 1)、(2, 2)、(2, 3) 和 (1, 2)。

  2. 让我们将列分成组,将具有相同值的相邻元素分组在一起(对于前面的示例,它将是 {(3, 1)}、{(2, 2)、(2, 3)} 和{(1, 2)}。现在我们可以解决一个标准问题:给定一个值数组h[i],找到每个组内所有ij的最大值min(h[i], h[i + 1], ..., h[j]) * (j - i + 1)(有一个线性使用堆栈的解决方案,如果需要,我可以详细说明)。它允许我们在线性时间内处理一行。

  3. 我们需要做的最后一件事是有效地计算每一行的 (value, height) 数组。对于第一行,这是微不足道的。所以我们可以逐行遍历所有行(当一个元素添加到列的底部时,(value,height)对以两种可能的方式发生变化:它变成(new_value,1)或(value,height) + 1))。

这些观察使我们能够在O(M) 时间内处理一行。总时间复杂度为O(N * M)

这是一些代码(它不是一个完整的实现,它可能包含错误):

int solve() {
    int res = 0;
    Pair[] valueForColumn = new Pair[rowsCount];
    for (int col = 0; col < columnsCount; col++)
        valueForColunm[col] = new Pair(matrix[0][col], 1);
    res = Math.max(res, solveForRow(valueForColumn); 
    for (int row = 1; row < rowsCount; row++) {
        for (int col = 0; col < columnsCount; col++)
            if (matrix[row][col] == matrix[row - 1][col]) {
                valueForColumn[col].second++;
            } else {
                valueForColumn[col].first = matrix[row][col];
                valueForColumn[col].second = 1;
            }
        }
        res = Math.max(res, solveForRow(valueForColumn));
   }
   return res;
}

int solveForRow(Pair[] valueForColumn) {
    List<Integer> group = new ArrayList<>();
    int res = 0;
    for (int i = 0; i < valueForColumn.length; i++) {
        group.add(valueForColumn[i].second);
        if (i == valueForColumn.length - 1 
                || valueForColumn[i].first != valueForColumn[i + 1].first) {
            res = Math.max(res, solveForGroup(group));
            group.clear();
        }
    }
    return res;
}

int solveForGroup(List<Integer> heights) {
    // a stack-based algorithm 
    // with linear time complexity mentioned in 2. goes here
}

【讨论】:

  • 我不明白您假设底行已修复的部分。你能解释一下吗
  • 另外,我们需要对每一行都这样做吗?首先我们从最下面一行开始,如果子矩阵不是这一行的一部分,那么我们需要移动到上面一行并遵循相同的算法对吗?你能提供任何伪代码或东西吗
猜你喜欢
  • 1970-01-01
  • 2011-04-17
  • 2016-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多