Дан массив целых чисел , и требуется переместить все нули в конец массива, сохраняя при этом относительный порядок ненулевых элементов.nums
Для лучшего понимания задачи рассмотрим несколько примеров:
Пример 1:
- Ввод:
= [0, 1, 0, 3, 12]nums - Вывод: [1, 3, 12, 0, 0]
Пример 2:
- Ввод:
= [0]nums - Вывод: [0]
Одним из оптимальных способов является использование алгоритма, работающего за линейное время и использующего только один проход по массиву.
Для решения этой задачи мы будем использовать алгоритм с двумя указателями. Один указатель будет указывать на текущий элемент, который мы рассматриваем, а второй будет указывать на место, куда мы должны переместить следующий ненулевой элемент.
- Мы будем двигать правый указатель
от начала массива к его концу.right - Если элемент, на который указывает правый указатель, не равен нулю, мы будем его обменивать с элементом, на который указывает левый указатель
. После этого мы увеличим левый указатель.left - После завершения цикла все ненулевые элементы будут находиться в начале массива, а все нули будут в его конце.
def moveZeroes(nums: List[int]) -> None:
left = 0
for right in range(len(nums)):
if nums[right] != 0 and nums[left] == 0:
nums[left], nums[right] = nums[right], nums[left]
if nums[left] != 0:
left += 1Разберем каждую строку кода из функции по порядку:moveZeroes
def moveZeroes(nums: List[int]) -> None:— Это объявление функцииdef moveZeroes(nums: List[int]) -> None:moveZeroes, которая принимает список целых чиселв качестве аргумента и не возвращает ничего (возвращаетnums). Возвращаемый тип указан в аннотации типов (Python type hints).None
left = 0— Создается переменнаяleft = 0, которая будет использоваться как левый указатель для перемещения ненулевых элементов.left
for right in range(len(nums)):— Это циклfor right in range(len(nums)):for, который итерируется по всем индексам элементов списка.nums— это правый указатель, который будет использоваться для перебора элементов массива.right
if nums[right] != 0 and nums[left] == 0:— Это условие проверяет, если элемент массива, на который указывает правый указатель (if nums[right] != 0 and nums[left] == 0:), не равен нулю и элемент массива, на который указывает левый указатель (nums[right]), равен нулю.nums[left]
nums[left], nums[right] = nums[right], nums[left]— Если условие из предыдущего шага выполняется, происходит обмен значениями между элементами массива на позицияхnums[left], nums[right] = nums[right], nums[left]иleft. Это позволяет переместить ненулевой элемент на место первого встреченного нуля.right
if nums[left] != 0:— После того как был выполнен обмен, проверяется элемент на позицииif nums[left] != 0:. Если он не равен нулю, это означает, что мы уже перенесли ненулевой элемент на его правильное место, иleftувеличивается наleftдля указания на следующую позицию в массиве.1
left += 1— Увеличение значенияleft += 1наleftдля перемещения левого указателя на следующий элемент.1
Этот код обеспечивает перемещение всех нулевых элементов в конец массива, при этом сохраняя порядок ненулевых элементов.
Сложность алгоритма
Временная сложность данного алгоритма составляет [math]O(n)[/math], где [math]n[/math] — количество элементов в массиве. Мы проходим по массиву только один раз.