Решён
Как бы вы ответили на этот вопрос? Тест для собеседования в IT

Игорь Белоусов Алгоритмы
1.1k
5

Готовлюсь к собесу в яндекс, дали задачу на алгоритмы. Вопрос такой: есть массив целых чисел, нужно найти два числа, сумма которых равна заданному target. Вернуть их индексы.

Пример: nums = [2, 7, 11, 15], target = 9. Ответ: [0, 1].

Я написал через двойной цикл O(n^2), но сказали что это медленно. Как бы вы сами ответили на этот вопрос на интервью? Что они хотят услышать?

Решение
59
Участник • 1 ответ

Two Sum через хэшмапу, классика.

def twoSum(nums, target):
    seen = {}
    for i, n in enumerate(nums):
        diff = target - n
        if diff in seen:
            return [seen[diff], i]
        seen[n] = i

O(n) по времени и памяти. На собесе сначала называешь наивное решение (у тебя оно есть), потом говоришь что можно лучше и объясняешь идею: для каждого числа считаешь дополнение до таргета и смотришь, видели ли мы его раньше. Именно это они и ждут.

Аватар Игорь Белоусов

Это именно то что мне нужно было, спасибо! Теперь понял логику. А почему seen[n] = i в конце, а не в начале цикла?

Аватар Галина Петровна

Потому что если положить сначала - можно использовать один и тот же элемент дважды. Например target=4, nums=[2,3]. Если сначала кладешь 2 в словарь, потом считаешь diff=2 и находишь его же. А задача требует два разных индекса.

24
Участник • 3 ответа

Твое O(n^2) решение правильное, просто медленное. На собесах в яндексе/гугле важна именно коммуникация процесса мышления, а не то что ты сразу выдашь идеальный код.

Алгоритм ответа такой:

  1. Подтверди что понял задачу, переспроси граничные случаи (пустой массив? дубликаты? несколько пар?)
  2. Назови наивное решение и его сложность
  3. Скажи что можно оптимизировать - предложи хэшмапу
  4. Напиши код, проговаривая каждую строку
  5. Сам прогони на примерах из условия

Эта задача это буквально первый номер на LeetCode (Two Sum). Прорешай там хотя бы 50 medium задач до собеса.

13
Эксперт • 2 ответа

Вообще-то O(n log n) тоже принимается если сортировать и использовать два указателя. Хэшмап не единственное решение, просто самое очевидное. Иногда интервьюер специально спрашивает про альтернативы после того как ты дал O(n).

Два указателя:

def twoSum(nums, target):
    indexed = sorted(enumerate(nums), key=lambda x: x[1])
    l, r = 0, len(indexed) - 1
    while l < r:
        s = indexed[l][1] + indexed[r][1]
        if s == target:
            return [indexed[l][0], indexed[r][0]]
        elif s < target:
            l += 1
        else:
            r -= 1

Но если просто хотят быстрое решение - хэшмап проще объяснять.

9
Участник • 1 ответ

Честно говоря задача настолько затаскана что любой нормальный интервьюер понимает - ты её мог вызубрить. Поэтому они потом дают вариации: а что если массив отсортирован, а что если нужно три числа, а что если числа с плавающей точкой. Хэшмапу выучи, но готовься объяснять почему именно она, а не просто рецитировать решение.

5
Эксперт • 2 ответа

Решение с хэшмапой хорошее, но ВНИМАНИЕ на детали реализации!

Если не учесть что в массиве могут быть дубли, можно получить баг. Например nums = [3, 3], target = 6. Твой словарь перезапишет первую тройку второй, и вернешь [1, 1] вместо [0, 1].

В решении выше этот кейс обработан правильно (сначала проверка, потом запись), но на собесе именно об этом и надо сказать сразу - показывает что думаешь об edge cases.

Написать ответ

Премодерация гостей

Вы отвечаете как гость. Ваш ответ будет скрыт до проверки модератором. Чтобы ответ появился сразу и вы получали репутацию — войдите в аккаунт.

Будьте вежливы и соблюдайте правила платформы.