【问题标题】:Sum of submatrices of bigger matrix较大矩阵的子矩阵之和
【发布时间】:2012-12-03 05:53:05
【问题描述】:

我有一个大矩阵作为输入,我有一个较小矩阵的大小。我必须计算所有可能的较小矩阵的总和,这些矩阵可以由较大的矩阵组成。

示例。 输入矩阵大小:4×4

矩阵:

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

输入较小的矩阵大小:3 × 3(不一定是正方形)

可能的更小的矩阵:

1 2 3
5 6 7
9 9 0

5 6 7
9 9 0
0 0 9

2 3 4
6 7 8
9 0 0

6 7 8
9 0 0
0 9 9

它们的总和,最终输出

14 18 22
29 22 15
18 18 18

我这样做了:

int** matrix_sum(int **M, int n, int r, int c)
{
    int **res = new int*[r];
    for(int i=0 ; i<r ; i++) {
        res[i] = new int[c];
        memset(res[i], 0, sizeof(int)*c);
    }

    for(int i=0 ; i<=n-r ; i++)
    for(int j=0 ; j<=n-c ; j++)
    for(int k=i ; k<i+r ; k++)
    for(int l=j ; l<j+c ; l++)
    res[k-i][l-j] += M[k][l];

    return res;
}

我想这太慢了,谁能推荐一个更快的方法?

【问题讨论】:

  • int** M 的意义何在?

标签: c++ c matrix submatrix


【解决方案1】:

您当前的算法是 O((m - p) * (n - q) * p * q)。最坏的情况是 p = m / 2 和 q = n / 2。

我要描述的算法将是 O(m * n + p * q),无论 p 和 q 是 O(m * n)。

该算法由 2 个步骤组成。

设输入矩阵A的大小为m x n窗口矩阵的大小为p x q

首先,您将创建一个与输入矩阵大小相同的预计算矩阵 B。预计算矩阵 B 的每个元素包含子矩阵中所有元素的总和,其左上元素在原始矩阵的坐标 (1, 1) 处,右下元素与我们正在计算的元素。

B[i, j] = Sum[k = 1..i, l = 1..j]( A[k, l] ) for all 1 <= i <= m, 1 <= j <= n

这可以在 O(m * n) 中完成,通过使用此关系计算 O(1) 中的每个元素:

B[i, j] = B[i - 1, j] + Sum[k = 1..j-1]( A[i, k] ) + A[j] for all 2 <= i <= m, 1 <= j <= n

B[i - 1, j],这是我们正在计算的子矩阵的所有内容,除了当前行,之前已经计算过了。您保留当前行的前缀总和,以便您可以使用它快速计算当前行的总和。

这是在 O(1) 中计算 B[i, j] 的另一种方法,使用 2D 前缀和的属性:

B[i, j] = B[i - 1, j] + B[i, j - 1] - B[i - 1, j - 1] + A[j] for all 1 <= i <= m, 1 <= j <= n and invalid entry = 0

然后,第二步是计算结果矩阵S,其大小为p x q。如果您进行一些观察,S[i, j] 是矩阵大小 (m - p + 1) * (n - q + 1) 中所有元素的总和,其左上角坐标为 (i, j) 并且右下角是 (i + m - p + 1, j + n - q + 1)。

使用预先计算的矩阵 B,您可以计算 O(1) 中任何子矩阵的总和。应用它来计算结果矩阵 S:

SubMatrixSum(top-left = (x1, y1), bottom-right = (x2, y2))
     = B[x2, y2] - B[x1 - 1, y2] - B[x2, y1 - 1] + B[x1 - 1, y1 - 1]

因此,第二步的复杂度将是O(p * q)。

最终复杂度如上所述,O(m * n),因为 p

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-28
  • 2014-01-27
  • 1970-01-01
相关资源
最近更新 更多