Реализовать функцию проверки наличия двух разных чисел в слайсе с заданной суммой без повторного использования числа
Что проверяют
Дойдёте ли вы до одного прохода с map вместо двойного цикла и заметите ли ловушку в формулировке «два разных числа». Задача стандартная, поэтому оценивают не факт решения, а аккуратность с граничными случаями и знание идиом Go.
Как отвечать
Идём по слайсу один раз, храним увиденные значения в множестве и перед добавлением текущего числа проверяем, встречалось ли его дополнение до целевой суммы:
func hasPair(nums []int, target int) bool {
seen := make(map[int]struct{}, len(nums))
for _, n := range nums {
if _, ok := seen[target-n]; ok {
return true
}
seen[n] = struct{}{}
}
return false
}Порядок проверки и вставки здесь не стилистика, а суть. Если сначала положить число в множество, то при целевой сумме, равной удвоенному значению, элемент найдёт сам себя и функция соврёт. Время линейное, map[int]struct{} не тратит память под значения, а ёмкость в make задана сразу, чтобы избежать перехеширования при росте.
Обязательно переспросите, что значит «разные»: разные позиции в слайсе или разные значения. В первом случае пара из двух одинаковых чисел допустима, во втором её надо отбрасывать, и код меняется. Если вход отсортирован, упомяните вариант с двумя указателями: линейное время без дополнительной памяти.
Где спотыкаются
Пишут двойной цикл и говорят, что так проще. На собеседовании по Go это читается как незнание того, что доступ к map в среднем константный, и следующий вопрос будет про сложность и про поведение на больших входах.
Второе: не думают про отрицательные числа и переполнение. Дополнение считается вычитанием, на границах диапазона int результат уходит за пределы типа, а тест с отрицательной целевой суммой кандидаты почти никогда не пишут сами.
Третье: возвращают индексы, когда просили факт наличия, или наоборот. Лишняя работа тут не плюс, но уточнить вслух, понадобятся ли потом сами числа, стоит: от этого зависит, класть в map пустую структуру или позицию.