Для целых чисел я обычно использую k% p, где p = размер хеш-таблицы и является простым числом, а для строк я выбираю хеш-код из класса String. Достаточно ли этого для интервью с крупной технологической компанией? - Феникс 2 дня назад
Возможно нет. Нередко нужно предоставлять хеш-функцию для хеш-таблицы, реализация которой вам неизвестна. Кроме того, если вы хэшируете способом, который зависит от реализации, использующей простое число сегментов, то ваша производительность может ухудшиться, если реализация изменится из-за новой библиотеки, компилятора, порта ОС и т. Д.
Лично я думаю, что на собеседовании важна четкое понимание идеальных характеристик универсального алгоритма хеширования, который заключается в том, что для любых двух клавиш ввода со значениями, меняющимися всего на один бит, каждый и каждый бит на выходе имеет около 50/50 шанса перевернуться. Я обнаружил, что это довольно нелогично, потому что во многих хэш-функциях, которые я впервые увидел, используются сдвиги битов и XOR, а перевернутый входной бит обычно переворачивает один выходной бит (обычно в другой битовой позиции, поэтому 1-input-bit -ффект-many -output-bits был небольшим откровением, когда я прочитал его в одной из книг Кнута. С этим знанием вы, по крайней мере, способны тестировать и оценивать конкретные реализации независимо от того, как они реализованы.
Один подход, который я упомяну, потому что он достигает этого идеала и легко запоминается, хотя использование памяти может сделать его медленнее, чем математические подходы (может быть и быстрее в зависимости от аппаратного обеспечения), заключается в простом использовании каждого байта на входе посмотреть таблицу случайных целых. Например, учитывая 24-битное значение RGB и int table[3][256]
, table[0][r] ^ table[1][g] ^ table[2][b]
является большим sizeof int
хеш-значением - действительно "идеальным", если входные данные случайным образом разбросаны по значениям int
(а не, скажем, с приращением - см. Ниже). ). Этот подход не идеален для ключей длинной или произвольной длины, хотя вы можете начать пересматривать таблицы и сдвигать значения по битам и т. Д.
Все, что сказано, вы можете иногда делать лучше, чем этот рандомизированный подход для конкретных случаев, когда вам известны шаблоны клавиш ввода и / или количество задействованных сегментов (например, вы можете Знайте, что клавиши ввода непрерывны от 1 до 100, и есть 128 блоков, так что вы можете передавать ключи без любых коллизий). Однако, если входные данные перестают соответствовать вашим ожиданиям, вы можете столкнуться с ужасными проблемами столкновения, в то время как «рандомизирующий» подход никогда не должен стать намного хуже, чем подразумевает load (size () / buckets). Еще одна интересная идея заключается в том, что если вам нужен быстрый и посредственный хеш, вам не обязательно включать все входные данные при создании хеша: например, в прошлый раз, когда я смотрел код хеширования строк в Visual C ++, он выделил десять букв, равномерно распределенных по тексту, для использования в качестве входных данных ....