Если вы хотите эффективный способ сделать это, вы должны учитывать локальность кэша ваших значений, сколько конверсии индекса вы делаете, сколько тестов границ вы делаете, и сколько требуется сравнение.
Первое, на что нужно обратить внимание, это то, что вам не нужно сравнивать левое и верхнее, когда вы уже сравниваете правое и нижнее. Это связано с тем, что тестирование влево / вверх будет происходить при тестировании вправо / вниз на следующей итерации. Так что сразу же это вдвое сокращает объем тестирования.
Первой оптимизацией было бы разделение операции на тесты строк и столбцов:
// 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;
}
}
Чтобы не делать два прохода по всему массиву, вам нужно их объединить, но он начинает становиться немного запутанным. Обратите внимание, что два отдельных прохода в настоящее время имеют разные границы (цикл проверки строк от столбца 1 до n, тогда как цикл проверки столбцов от строки 0 до n-1).
Объединение циклов имеет смысл только в том случае, если n
достаточно велико и если абсолютно критично, что этот фрагмент кода быстр. Идея состоит в том, чтобы выполнить один проход через весь массив, избегая проблем с такими вещами, как пропадание кэша L1 во втором проходе.
Это будет выглядеть примерно так:
const int *row0ptr = v, *row1ptr = v + n, *end = v + n * n
for ( ; row1ptr != end; row0ptr = row1ptr, row1ptr += n)
{
// Test first column
if (row0ptr[0] == row1ptr[0]) return false;
// Test row0 and remaining columns
for (int col = 1; col < n; col++) {
if (row0ptr[col-1] == row0ptr[col]) return false;
if (row0ptr[col] == row1ptr[col]) return false;
}
}
// Test last row
for (int col = 1; col < n; col++) {
if (row0ptr[col-1] == row0ptr[col]) return false;
}