Допустим, у нас есть список, заполненный числами. Надо выяснить, все ли числа в нем уникальные или есть повторения.
Самый короткий способ решить задачу – это преобразовать список во множество, сравнить его длину с длинной списка. Поскольку во множестве не может быть повторений, то, если в списке они есть, соответствующее ему множество окажется короче.
Теперь попробуем решить задачу способом более близким, скажем так, к классическим алгоритмам, используя только список как аналог массива.
В этом случае алгоритм поиска совпадений может быть таким. Берем сначала первый элемент и по-очереди сравниваем его со всеми стоящими после него. Если будет найдено совпадение, выведем соответствующее сообщение и завершим поиск.
Если нет, берем второй элемент и начинаем сравнивать его со всеми стоящими после него. Сравнивать с впереди стоящим не надо, так как такое сравнение уже было, когда по списку прогонялся первый элемент.
Если второй элемент ни с чем не совпадет, перейдем к третьему и будем сравнивать его с расположенными после него. И так далее.
Если в результате всех сравнений совпадений не найдется, делается вывод, что все элементы в списке уникальны.
Выводить на экран ту или иную надпись будем в зависимости от значения переменной unique.
Изначально присвоим ей истину, предполагая, что все элементы уникальны.
Нам надо перебрать все элементы списка кроме последнего, так как его уже не с чем будет сравнивать. Перебирать будем индексы элементов, а не сами значения. В данном случае индексы от 0 до восьми.
Во внутреннем цикле будут перебираться элементы стоящие после текущего i. Значит, их индексы будут от следующего за i, до последнего. Последний имеет индекс 9. Если N имеет значение 10, то функция range будет генерировать числа до девяти.
Надо сравнивать элемент в позиции i со значением в текущей позиции j.
Если они равны, значит в списке есть повторения. Тогда надо поменять значение unique на False. Программа будет работать и так. Но всё же здесь важно завершить поиск совпадений, так как смысла искать дальше уже нет.
И вот тут появляется проблема. Оператор break прервет только внутренний цикл, но не внешний.
Можем в этом убедиться, выводя итерации.
Несмотря на то, что одинаковые были обнаружены уже здесь, внешний цикл прокрутился девять раз.
Мало кто знает, но у цикла for может быть ветка else. Она выполняется, когда цикл завершается без break. Если срабатывает прерывание, то тело else не выполняется.
В нашей программе если break срабатывает во внутреннем цикле, надо чтобы срабатывал break и во внешнем.
Но чтобы не доходить до внешнего break, когда внутренний цикл завершает свою работу в нормальном режиме, без прерывания, в ветке else используем оператор continue.
Хотя ветка else и относится к вложенному циклу, но прерывать текущую итерацию она будет у внешнего цикла.
То есть если совпадений не было найдено, выполнится continue, поток выполнения уйдет на следующую итерацию внешнего цикла и до внешнего break так и не дойдет.
Если же здесь сработает break, то он сработает и здесь. Потому что ветка else будет пропущена.
Более практичным вариантом может быть использование функции. Потому что здесь можно выйти из любого места с помощью оператора return.
Не важно какова степень вложенности цикла for. Выход происходит из всей функции вообще. До второго return мы можем дойти, только если не вышли ранее.
Еще один вариант решения задачи – это использовать метод count, который есть у списков. Он возвращает, сколько раз встречается значение в списке. Обратите внимание, здесь перебираем не индексы элементов, а сами значения списка.
Если количество какого-то элемента больше единицы, значит есть одинаковые.
Текстовое описание решения задачи и исходный код программы: https://younglinux.info/python/task/u...
Больше задач: https://younglinux.info/python/task
Приложение для андроид: https://play.google.com/store/apps/de...
Купить PDF-версию (100 задач): https://younglinux.info/store/store.h...
Информация по комментариям в разработке