以下是旨在在一维向量中相邻数字之间进行相等性测试的功能。
此一维矢量的值将代表一个nxn网格。 [v是向量]
当它们相等时,它返回false。
例如考虑以下3x3网格:
i\j| 0 | 1 | 2
0 | 1 | 2 | 3
1 | 4 | 5 | 6
2 | 7 | 8 | 9
我编写的代码的问题在于,并非网格中的所有数字都会有其他4个相邻数字,并测试不存在的索引,例如,当尝试比较网格左上角数字上方的数字时(示例中为1)可能会导致一些不准确的结果。
除此之外,我写的内容似乎并不是解决问题的最有效方法。当然,除了列出5个新变量之外,还有一种更简单的方法吗?
for( int i= 0; i < n ; i++ ){
for( int j = 0; j < n; j++){
int x = v[convert(i, j, n)];
int c = v[convert(i-1, j, n)];
int s = v[convert(i+1, j, n)];
int b = v[convert(i, j+1, n)];
int n = v[convert(i, j-1, n)];
if (x == c || x == s || x == b || x == n ) {
return false;
}
}
}
//another function used to convert 2d into 1D index
int convert(int row, int col, int rowlen){
return row*rowlen+col;
}
我将不胜感激。
答案 0 :(得分:1)
首先,我建议您打破逻辑,因为它变得非常令人费解。但是类似的方法行之有效,它可以通过在i
和j
上添加额外的检查来避免走出网格,并且可以避免对convert
的不必要的调用,因为如果其中一个较早的测试为真,以后的测试不会执行。
int x = v[convert(i, j, n)];
if (i > 0 && x == v[convert(i-1, j, n)])
return false;
if (i < n - 1 && x == v[convert(i+1, j, n)])
return false;
if (j > 0 && x == v[convert(i, j-1, n)])
return false;
if (j < n - 1 && x == v[convert(i, j+1, n)])
return false;
答案 1 :(得分:1)
如果您想要一种有效的方法来执行此操作,则应考虑值的缓存位置,进行多少索引转换,进行多少边界测试以及需要进行多少比较。
首先要注意的是,当您已经将右侧和下方进行比较时,无需将其与左侧和上方进行比较。这是因为在下一次迭代中向右/向下测试时将发生向左/向上测试。因此,立即,测试量减少了一半。
第一个优化是将操作分为行测试和列测试:
Closure
为避免两次遍历整个数组,您需要将它们组合在一起,但开始变得有些混乱。请注意,两个单独的通道当前具有不同的界限(行测试循环从第1列到n,而列测试循环从第0到n-1)。
仅当// Test adjacency in rows
for (const int *rowptr = v, *end = v + n * n;
rowptr != end;
rowptr += n)
{
for (int col = 1; col < n; col++) {
if (rowptr[col-1] == rowptr[col]) return false;
}
}
// Test adjacency in columns
for (const int *row0ptr = v, *row1ptr = v + n, *end = v + n * n;
row1ptr != end;
row0ptr = row1ptr, row1ptr += n)
{
for (int col = 0; col < n; col++) {
if (row0ptr[col] == row1ptr[col]) return false;
}
}
很大并且对于这段代码快速至关重要时,组合循环才有意义。这个想法是对整个数组执行一次遍历,避免第二遍遍发生诸如L1缓存未命中之类的问题。
它看起来像这样:
n