Алгоритмы с нуля
Хеширование: тест с выбором ответа
Шесть вопросов, которые проходят через весь юнит. Каждый — это решение, которое вы принимаете, когда тянетесь к hash map на собеседовании или в реальном коде: не определение для пересказа, а tradeoff, который нужно защитить.
Убедитесь, что вы связываете hash function, обработку collision, load factor и amortized resize с повседневными паттернами — seen, частотный подсчёт, группировка, — к которым вели отдельные уроки.
Hash set даёт O(1) поиск в среднем. На каком единственном факте на самом деле держится это «в среднем»?
Два разных ключа хешируются в один и тот же индекс бакета. При separate chaining что происходит и сколько это стоит?
В таблице 10 элементов на 5 бакетов, и она никогда не делает resize. Если продолжать вставлять без resize, что произойдёт со стоимостью поиска и почему?
Вставку в hash table называют O(1) amortized, но одна вставка может стоить O(n). Как оба утверждения верны одновременно?
Нужно определить, повторяется ли хоть одно значение в потоке, и отдельно — найти два числа, дающих в сумме target. Какой паттерн хеширования подходит каждому?
Сервис хеширует строки от пользователя в таблицу, а атакующий заливает входами, специально подобранными так, чтобы все коллидировали в один бакет. В чём отказ и в чём настоящий фикс?
Сквозная линия юнита — одна цепочка рассуждений: hash function превращает ключ в индекс для доступа O(1) в среднем; collision неизбежны, и chaining хранит их в списках на бакет; load factor задаёт среднюю длину цепочки, поэтому таблица делает resize — удвоение и перехеширование, — чтобы держать её ограниченной: O(n) на resize, но O(1) amortized; а сверху лежат повседневные паттерны — seen, дополнение, частотный подсчёт, группировка. Та же механика деградирует к O(n) при плохой или враждебной hash function, поэтому рандомизированный хеш важен для недоверенного входа.