Это как минимум O (n * m), как бы вы его ни разрезали - вам придется хотя бы раз взглянуть на каждую ячейку. Экономия - это место, где вы накапливаете счет каждого значения, прежде чем искать наиболее распространенное; если ваши целые числа изменяются в относительно небольшом диапазоне (скажем, uint16), то вы можете просто использовать плоский массив вместо карты.
Полагаю, вы также можете сохранить текущий счет x , y текущего верхнего и второго ближайшего кандидата на "наиболее распространенный" и ранний выход, как только вы ' осталось меньше (n * m) - (xy) ячеек, так как в этот момент участник, занявший второе место, не сможет опередить лучшего кандидата.
Такие целочисленные операции довольно быстрые; даже для мегапиксельного изображения алгоритм перебора должен занимать всего пару миллисекунд.
Я заметил, что вы отредактировали свой первоначальный вопрос, чтобы сказать, что значение пикселей от 0..255 - в этом случае, безусловно, используйте простой плоский массив; он достаточно мал, чтобы легко помещаться в d1-кэш, и поиск в плоском массиве очень быстр.
[править]: Работа со случаем «нет наиболее распространенного числа» очень проста после того, как вы построите массив гистограмм: все, что вам нужно сделать, это пройтись по нему, чтобы найти «большинство» и «вторые наиболее» общие числа; если они одинаково часты, то по определению нет ни одного наиболее распространенного.
const int numLevels = 360; // you said each cell contains a number [0..360)
int levelFrequencyCounts[numLevels]; // assume this has been populated such that levelFrequencyCounts[i] = number of cells containing "i"
int mostCommon = 0, runnerUp = 0;
for (int i = 1 ; i < numLevels ; ++i)
{
if ( levelFrequencyCounts[i] > levelFrequencyCounts[mostCommon] )
{
runnnerUp = mostCommon;
mostCommon = i;
}
}
if ( levelFrequencyCounts[mostCommon] != levelFrequencyCounts[runnerUp] )
{
return mostCommon;
}
else
{
return CenterOfInputData; // (something like InputData[n/2][m/2])
}