Программа курса:

1.1 - Часть 1 1.2 - Часть 2 1.3 - Часть 3 1.4 - Часть 4 1.5 - Часть 5 1.6 - Часть 6 1.7 - Часть 7 1.8 - Часть 8 1.9 - Часть 9 1.10 - Часть 10 1.11 - Часть 11 1.12 - Часть 12
2.1 - Часть 1 2.2 - Часть 2 2.3 - Часть 3 2.4 - Часть 4 2.5 - Часть 5 2.6 - Часть 6
3.1 - Часть 1

Разбор задачи: Удаление дубликатов из отсортированного массива

Предложенный нами код решения:

def remove_duplicates(nums):
    # Указатель для уникальных элементов
    if not nums:
        return 0
    unique_index = 0
    for i in range(1, len(nums)):
        if nums[i] != nums[unique_index]:
            unique_index += 1
            nums[unique_index] = nums[i]
    return unique_index + 1

Разбор:

  1. Проверка на пустой список:

    if not nums:
        return 0
    

    Здесь проверяется, является ли список пустым. Если список пустой (nums равно []), функция немедленно возвращает 0, потому что в пустом списке нет уникальных элементов.

  2. Инициализация указателя для уникальных элементов:

    unique_index = 0
    

    Переменная unique_index будет использоваться для хранения индекса, на котором в массиве должны быть записаны уникальные элементы. Изначально этот индекс указывает на первый элемент массива (индекс 0), так как первый элемент всегда уникален сам по себе.

  3. Основной цикл:

    for i in range(1, len(nums)):
        if nums[i] != nums[unique_index]:
            unique_index += 1
            nums[unique_index] = nums[i]
    

    Этот цикл начинается с индекса 1 и продолжается до конца массива. Он выполняет следующие шаги:

    • Сравнение текущего элемента с последним уникальным элементом: Для каждого элемента в массиве начиная с индекса 1, проверяется, отличается ли он от последнего уникального элемента, который находится на позиции unique_index.
    • Если элемент отличается от предыдущего уникального: Если текущий элемент (nums[i]) отличается от последнего уникального элемента (nums[unique_index]), это означает, что мы нашли новый уникальный элемент. В этом случае:
      • Увеличиваем unique_index, чтобы указать на следующее место для уникального элемента.
      • Записываем текущий элемент на позицию unique_index, тем самым заменяя старый дубликат новым уникальным значением.

    Таким образом, этот цикл гарантирует, что на позициях с индексами от 0 до unique_index будут находиться все уникальные элементы массива в том же порядке.

  4. Возвращаем количество уникальных элементов:

    return unique_index + 1
    

    После выполнения цикла переменная unique_index указывает на последний уникальный элемент в списке. Поскольку индексация в Python начинается с нуля, для получения количества уникальных элементов нужно добавить 1 к unique_index. Это и есть количество уникальных элементов в списке.

Пример:

Рассмотрим пример, чтобы понять, как работает функция:

nums = [0, 0, 1, 1, 1, 2, 2, 3, 3, 4]
result = remove_duplicates(nums)

Шаги выполнения:

  1. В начале переменная unique_index равна 0, а список nums = [0, 0, 1, 1, 1, 2, 2, 3, 3, 4].
  2. После первого шага цикла (i=1), nums[1] == nums[0], то есть элемент 0 повторяется, ничего не меняется.
  3. На втором шаге (i=2), nums[2] != nums[0] (1 отличается от 0), поэтому:

    • unique_index увеличивается на 1, становится равным 1.
    • Элемент 1 записывается на позицию nums[1].

    После этого список будет выглядеть так: nums = [0, 1, 1, 1, 1, 2, 2, 3, 3, 4].

  4. На третьем шаге (i=3), nums[3] == nums[1] (1 повторяется), ничего не меняется.
  5. На четвёртом шаге (i=4), снова nums[4] == nums[1], ничего не меняется.
  6. На пятом шаге (i=5), nums[5] != nums[1] (2 отличается от 1), поэтому:

    • unique_index увеличивается на 1, становится равным 2.
    • Элемент 2 записывается на позицию nums[2].

    После этого список будет выглядеть так: nums = [0, 1, 2, 1, 1, 2, 2, 3, 3, 4].

  7. Следующие шаги аналогичны. В итоге, после завершения цикла, массив будет иметь вид:

    nums = [0, 1, 2, 3, 4, 2, 2, 3, 3, 4]
    

    Функция вернёт 5, что соответствует количеству уникальных элементов.

 



Комментарии

xsnm_avatar
xsnm
,
1 месяц, 29 дней назад

Это не правильное решение. Потеря уникальности элементов списка. Решение через присвоения не верно.

0
admin_avatar
admin
,
1 месяц, 28 дней назад

xsnm, Почему классическое решение с двумя указателями и со сложностью O(n) неправильное?

0
xsnm_avatar
xsnm
,
1 месяц, 28 дней назад

nums[unique_index] = nums[i] # "=" Это оператор присвоения. То есть элемент nums[unique_index] копия элемента nums[i]. Копия.....
# А это не уникальный элемент. Не оригинал. Где оригинал??????. Если решать то, первый элемент "1" в ряде оригинал и его нельзя трогать и так далее.
# "0" по умолчанию.
 

0
admin_avatar
admin
,
1 месяц, 27 дней назад

xsnm, Так уникальность это не про то, что нельзя использовать ссылки и тд, если хотите, вы можете посмотреть решебники на гитхабе подобных задач и там решения будут с более худшей сложность O(n^2), но найти решение с более эффективной сложностью вам будет труднее, если список не был бы заранее отсортирован, пришлось бы использовать множество. Если у вас есть более хорошее и правильное на ваш взгляд решение, приложите его пожалуйста, все ваши предложения я всегда рассматриваю на всех курсах и готов вносить правки, если вижу на основе ваших примеров реальные ошибки и неточности, особенно в плане этого задачника, ибо он ещё не прошёл полировку. Буду рад любой конструктивной критике). 

0
admin_avatar
admin
,
1 месяц, 27 дней назад

xsnm, Отвечая на вопрос - "Где оригинал?"

Оригиналы элементов остаются в массиве, просто они могут перемещаться ближе к началу.

Алгоритм не удаляет элементы из памяти, а переупорядочивает их, чтобы уникальные шли подряд.


В Python числа (и неизменяемые объекты) передаются по значению, но в списке мы работаем с ссылками.

Присваивание nums[unique_index] = nums[i] не создает новый объект, а просто копирует ссылку.

Если бы в списке были сложные объекты (например, списки или словари), то копировалась бы ссылка, но в данном случае (числа) разницы нет.

0
xsnm_avatar
xsnm
,
1 месяц, 27 дней назад

0 [0, 0, 1, 1, 1, 2, 2, 3, 3, 4]
1 [0, 0, 1, 1, 1, 2, 2, 3, 3, 4] 2
2 [0, 1, 1, 1, 1, 2, 2, 3, 3, 4] Вопрос. Было 3 шт. - "1" стало 4 шт.
1 [0, 1, 1, 1, 1, 2, 2, 3, 3, 4] 5
2 [0, 1, 2, 1, 1, 2, 2, 3, 3, 4]
1 [0, 1, 2, 1, 1, 2, 2, 3, 3, 4] 7 и так далее.....
2 [0, 1, 2, 3, 1, 2, 2, 3, 3, 4]
1 [0, 1, 2, 3, 1, 2, 2, 3, 3, 4] 9
2 [0, 1, 2, 3, 4, 2, 2, 3, 3, 4]  а здесь одна "1". Она уникальна???? так с остальными
5
r [0, 1, 2, 3, 4, 2, 2, 3, 3, 4]
 

0
admin_avatar
admin
,
1 месяц, 27 дней назад

xsnm, Ответ на вопрос:

"А здесь одна '1'. Она уникальна???? Так с остальными..."

Да, она уникальна в контексте задачи.

В первых k=5 элементах ([0, 1, 2, 3, 4]) "1" встречается только 1 раз (на позиции nums[1]).

Остальные "1" находятся после k-го элемента и не учитываются в результате.

Алгоритм корректно перемещает уникальные элементы в начало, сохраняя их порядок.

Никакие элементы не копируются — просто меняются ссылки внутри массива.

"Оригиналы" не теряются, они либо остаются на месте, либо перемещаются в начало.

Всё, что после nums[:k], не имеет значения (по условию задачи).

0
DeaglenS_avatar
DeaglenS
,
1 месяц, 8 дней назад

def remove_duplicates(nums):
 nums_set = set(nums)
 nums[:] = sorted(nums_set)
 return len(nums_set)

0

Вы должны Войти или Зарегистрироваться чтобы оставлять комментарии