Алгоритминутка

Алгоритминутка


Дан список целых чисел nums. Вернуть все тройки чисел [nums[i], nums[j], nums[k]], такие что i != j,i != k, j != k и nums[i] + nums[j] + nums[k] = 0. Имеется ввиду неповторяющиеся тройки, то есть тройки [-1, 0, 1] и [0, -1, 1] считаем одинаковыми.


Примеры:

1) nums = [-1,0,1,2,-1,-4] —> [[-1,-1,2],[-1,0,1]]
2) nums = [0,1,1] —> []
3) nums = [0,0,0] —> [[0,0,0]]


На самом деле отличие от задачи про сумму двух элементов не только в том, что элементов стало больше. В предыдущей задачи гарантировалось одно решение, здесь же может быть несколько.


Решение №1

0) Заводим список answer, в котором будем хранить подходящие тройки чисел. Запустим три цикла по списку с индексами i, j, k

1) Если мы нашли тройку nums[i] + nums[j] + nums[k] = 0 и все индексы различны, то сортируем ее и проверяем есть ли такая в answer. Если есть, то пропускаем, если нет, то добавляем. Сортировать нужно, чтобы в ответе не было одинаковых троек.

2) После завершения циклов возвращаем answer.


def solve(nums):
  answer = []

  for i in range(len(nums)):
    for j in range(i+1, len(nums)):
      for k in range(j+1, len(nums)):
        if nums[i] + nums[j] + nums[k] == 0:
          candidate = sorted([nums[i], nums[j], nums[k]])
          if candidate not in answer:
            answer.append(candidate)
  return answer


Решение №2

0) Заводим список answer, в котором будем хранить подходящие тройки чисел. Сортируем список nums.

1) Запускаем цикл по списку с индексом i. Вводим два дополнительных указателя: l = i+1 и r = n-1 (n — длина списка nums). 

2) Далее перебираем тройки nums[i] + nums[l] + nums[r] пока l будет меньше r. Если это сумма меньше 0, то двигаем l на 1 вправо, если больше нуля, то двигаем r на 1 влево. 

3) Если же эта сумма равна нулю, то сохраняем эту тройку в answer. Но нужно рассмотреть случай, если nums[l] = nums[l+1], тогда на следующей итерации добавиться такая же тройка. Чтобы этого избежать будем отдельным циклом сдвигать индекс l пока не встретим отличный от этого элемент. Аналогично и с индексом r.

4) Так как список отсортированный, то после того как мы встретили положительное число nums[i] > 0, цикл можно обрывать (тройки с отрицательными числами уже проверили)


def solve(nums):
  nums.sort()
  answer = []
  n = len(nums)

  for i in range(n - 2):
    if nums[i] > 0:
      break
    if i > 0 and nums[i] == nums[i-1]:
      continue
    l = i + 1
    r = n - 1
    while l < r:
      total = nums[i] + nums[l] + nums[r]
      if total < 0:
        l += 1
      elif total > 0:
        r -= 1
      else:
        triplet = [nums[i], nums[l], nums[r]]
        answer.append(triplet)
        while l < r and nums[l] == triplet[1]:
          l += 1
        while l < r and nums[r] == triplet[2]:
          r -= 1
  return answer

Report Page