Большинство людей здесь предложили решения, которые, вероятно, будут быстрыми (на самом деле то, что использует только 2 МБ, вероятно, приемлемо в отношении использования памяти и очень быстрое; решение с хешем может быть даже быстрее, но оно определенно будет использовать больше, чем 2 МБ памяти). Программирование - это всегда компромисс между использованием памяти и временем процессора. Обычно вы можете получать результаты быстрее, если вы хотите «тратить» больше памяти или же вы можете получать результаты медленнее, «тратя» больше времени на вычисления, однако это обычно экономит вам много памяти.
Вот одно решение, которое никто еще не предлагал. Вероятно, это тот, который стоит меньше всего памяти (вы можете оптимизировать его, так что он вряд ли будет использовать больше памяти, чем необходимо для сохранения изображения в памяти, однако изображение будет изменено, хотя вам, возможно, придется сначала скопировать его). Я сомневаюсь, что это может побить решение по хешу или битовой маске по скорости, просто интересно, если память - ваша самая большая проблема.
Сортировка пикселей на изображении по цвету. Вы можете легко преобразовать каждый пиксель в 32-разрядное число, и 32-разрядные числа можно сравнить друг с другом, причем одно число меньше другого, больше или равно. Если вы используете быструю сортировку, для сортировки не требуется дополнительного места для хранения, кроме дополнительного стека. Если вы используете Shellsort, дополнительная память вообще не требуется (хотя Shellsort будет работать намного медленнее, чем Quicksort).
int num = (RED << 16) + (GREEN << 8) + BLUE; </p>
После того, как вы отсортировали пиксели подобным образом (что означает, что вы переставили их в пределах изображения), все пиксели одинакового цвета всегда будут рядом друг с другом. Таким образом, вы можете только один раз перебрать изображение и посмотреть, как часто меняется цвет. Например. Вы сохраняете текущий цвет пикселя в (0, 0) и запускаете счетчик со значением 1. Следующий шаг - переход к (0, 1). Если он того же цвета, что и раньше, ничего не делать, переходите к следующему пикселю (0, 2). Однако, если это не то же самое, увеличьте счетчик на единицу и запомните цвет этого пикселя для следующей итерации.
Как только вы посмотрите на последний пиксель (и, возможно, снова увеличите счетчик, если он не совпадает со вторым последним пикселем), счетчик содержит количество уникальных цветов.
Итерации по всем пикселям хотя бы один раз - это то, что вы должны делать в любом случае, независимо от решения, поэтому оно не влияет на то, что это решение медленнее или быстрее, чем другие решения. Скорость этого алгоритма зависит от того, насколько быстро вы можете отсортировать пиксели изображения по цвету.
Как я уже сказал, этот алгоритм легко обойти, когда скорость - ваш главный концерт (другие решения здесь, вероятно, все быстрее), но я сомневаюсь, что он может быть побежден, когда использование памяти является вашей главной задачей, поскольку, кроме счетчика, достаточно место для хранения одного цвета и место для самого изображения, ему потребуется дополнительная память, только если выбранный вами алгоритм сортировки нуждается в этом.