较大矩阵的子矩阵的和

Sum of submatrices of bigger matrix

本文关键字:      更新时间:2023-10-16

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

示例。输入矩阵大小: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;
}

我想这太慢了,有人能建议一条更快的路吗?

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

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

该算法由两个步骤组成。

设输入矩阵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

然后,第二步是计算大小为p x q的结果矩阵S。如果你观察一下,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<=m和q<=n.

相关文章:
  • 没有找到相关文章