- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我试图从矩阵 NXM 中找到任何子矩阵 AXB 的最大元素。我实现了稀疏树方法。但是我无法对此进行优化。其实我需要解决范围查询,所以我需要优化代码。在进行预计算时,对于任何 N,M 值,它都需要 O(NMlog(N)log(M)) 时间复杂度。我怎样才能将其改进为 (N*M)。这是我的预计算代码
for(int i=0; i<n;i++)
for(int j=0; j<m;j++)
cin>>arr[i][j];
for(int i=0; pow(2,i) <= n; i++)
for(int j=0; pow(2,j) <= m; j++)
for(int x=0; x + pow(2,i)-1 < n; x++)
for(int y = 0; y + pow(2,j) -1 < m; y++)
{
i=(int)i;
j=(int)j;
if (i == 0 && j == 0)
M[x][y][i][j] = arr[x][y];
else if (i == 0)
M[x][y][i][j] = maxi(2,M[x][y][i][j-1], M[x][(int)(y+pow(2,(j-1)))][i][j-1]);
else if (j == 0)
M[x][y][i][j] = maxi(2,M[x][y][i-1][j], M[(int)(x+ pow(2,(i-1)))][y][i-1][j]);
else
M[x][y][i][j] = maxi(4,M[x][y][i-1][j-1], M[(int)(x + pow(2,(i-1)))][y][i-1][j-1], M[x][(int)(y+pow(2,(j-1)))][i-1][j-1], M[(int)(x + pow(2,(i-1)))][(int)(y+pow(2,(j-1)))][i-1][j-1]);
}
对于输入 x,y,x1,y1
k = log(x1 - x + 1);
l = log(y1 - y + 1);
int max_element = max(4,M[x][y][k][l], M[(int)(x1 - pow(2,k) + 1)][y][k][l], M[x][(int)(y1 - pow(2,l) + 1)][k][l], M[(int)(x1 - pow(2,k) + 1)][(int)(y1 - pow(2,l) + 1)][k][l]);
如何提高这段代码的性能。请帮忙。
最佳答案
此解决方案并不比 O(N*M*Log(N)*Log(M))
好,但比您的实现要好。
通过查看你的for
循环和访问数组M
的执行顺序,会有太多的内存跳转和缓存未命中,导致程序运行缓慢。
例子:-
查看以下循环所用的时间:
int M[1000][1000][11][11];
for(int i = 0 ; i <= 10 ; i++){
for(int j = 0 ; j <= 10 ; j++){
for(int x = 0 ; x < 1000 ; x++){
for(int y = 0 ; y < 1000 ; y++){
M[x][y][i][j] = 1;
}
}
}
}
上述执行需要 1.9 秒。
int M[11][11][1000][1000];
for(int i = 0 ; i <= 10 ; i++){
for(int j = 0 ; j <= 10 ; j++){
for(int x = 0 ; x < 1000 ; x++){
for(int y = 0 ; y < 1000 ; y++){
M[i][j][x][y] = 1;
}
}
}
}
而这个只需要 0.2 秒。因此,请始终尝试编写循环,以便顺序访问内存。
有关更多详细信息,您可以阅读 here .
因此,如果您按以下方式更改代码,速度会快得多:
M[Log(n)][Log(m)][n][m];
for(int i=0; (1<<i) <= n; i++)
for(int j=0; (1<<j) <= m; j++)
for(int x=0; x + (1<<i)-1 < n; x++)
for(int y = 0; y + (1<<j) -1 < m; y++)
{
i=(int)i;
j=(int)j;
if (i == 0 && j == 0)
M[i][j][x][y] = arr[x][y];
else if (i == 0)
M[i][j][x][y] = maxi(2,M[i][j-1][x][y], M[i][j-1][x][(y+(1<<(j-1)))]);
else if (j == 0)
M[i][j][x][y] = maxi(2,M[i-1][j][x][y], M[i-1][j][(x+ (1<<(i-1)))][y]);
else
M[i][j][x][y] = maxi(4,M[i-1][j-1][x][y], M[i-1][j-1][(x + (1<<(i-1)))][y], M[i-1][j-1][x][(y+(1<<(j-1)))], M[i-1][j-1][(x + (1<<(i-1)))][(y+(1<<(j-1)))]);
}
如果您计算 log()
的次数(即 10^5 或更大的数量级)超过您可以使用 31-__builtin_clz() 的次数,还可以进行另一项优化
而不是 log()
。
k = 31-__builtin_clz(x1 - x + 1);
l = 31-__builtin_clz(y1 - y + 1);
int max_element = max(4,M[k][l][x][y], M[k][l][(x1 - (1<<k) + 1)][y], M[k][l][x][(y1 - (1<<l) + 1)], M[k][l][(x1 - (1<<k) + 1)][(y1 - (1<<l) + 1)]);
关于c++ - NXM矩阵的所有AXB子矩阵中的最大元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37754330/
我只是不断地用这个碰壁,我无法解决它。我正在尝试获取一个执行为的正则表达式: (axb|cxd) 除了在表达式中不重复 x(因为它是很长的编码匹配表达式)。这是针对一个大字符串进行测试的,我只需要匹配
所以,基本上,请检查下图: 这是一个 4x5 的网格,但是实际的挑战需要您输入网格尺寸。所以,我的工作是编写一个程序来计算你的转弯次数(在本例中为红点)。起始位置始终在左下角。这家伙正在按时钟的箭头(
我正在关注 https://taninamdar.files.wordpress.com/2013/11/submatrices3.pdf找到矩阵的子矩阵总数。但是我不知道如何找到矩阵中存在多少个给定
我是一名优秀的程序员,十分优秀!