Python. Простые алгоритмы
Рассматриваются алгоритмы линейной обработки списков, строк - это последовательный поиск и нахождение заданного значения, когда нужно просмотреть все элементы с первого до последнего. Как только будет найден элемент, равный заданному значению, необходимо вывести найденное значение и завершить поиск. Такой алгоритм является простейшим алгоритмом поиска. Сложность поиска O(n).
В программировании «О» большое описывает наихудший сценарий. Допустим, у нас есть массив чисел, где мы должны найти какое-то определенное число при помощи цикла for. Оно может быть найдено при любой итерации, и чем раньше, тем быстрее функция завершит работу. О-нотация всегда указывает на верхнюю границу, т. е., описывает случай, когда алгоритму придется осуществить максимальное количество итераций, чтобы найти искомое число. Как, например, в том случае, если это число окажется последним в перебираемом массиве
a = 5
b = 15
c = 25
Способ №1. Использование оператора if else
if a > b:
if a > c:
print(a)
else:
print(c)
else:
if b > c:
print(b)
else:
print(c)
#25
Временная сложность: O(1)– постоянная временная сложность
Пояснения
- O(1) означает постоянное время выполнения. Независимо от размера входных данных алгоритм будет иметь одинаковое время выполнения.
- Нотация большого «О» используется не для оценки конкретного времени работы кода. Ее используют для оценки того, как быстро возрастает время обработки данных алгоритмом в привязке к объему этих данных.
- Временная сложность алгоритма определяет число шагов, которые должен предпринять алгоритм, в зависимости от объема входящих данных (n).
Способ №2. Использование оператора elif
if a > c and a > b : print(a)
elif b > a and b > c : print(b)
else: print(c)
#25
Временная сложность: O(1)
Способ №3. Использование дополнительной переменной
mx = a
if b > mx:
mx = b
if c > mx:
mx = c
print(mx)
#25
Временная сложность: O (1)
Способ №4. Использование функции max()
mx = max(a,b,c)
print(mx)
#25
Временная сложность: O (1)
Способ №5. Использование функции сортировки sorted()
m = sorted([a,b,c])
print(m[-1])
#25
Временная сложность: O(n log n),
В Python в алгоритмах сортировки используется алгоритм Timsort, временная сложность которого определяется зависимость O(n log n), где n– количество элементов в списке.
a = [1,2,3,4]
Способ № 1 использование цикла for
for x in a:
print(x, end = ' ')
#1 2 3 4
Временная сложность: O (n)
Способ № 2 использование цикла For и range
for i in range(len(a)):
print(a[i], end = ' ')
#1 2 3 4
Временная сложность: O (n)
Способ № 3 использование цикла while
n = len(a)
i = 0
while i<n:
print(a[i], end=' ')
i+=1
#1 2 3 4
Временная сложность: O (n)
Способ № 4. Использование генератора списка
[print(x, end = ' ') for x in a]
#1 2 3 4
Временная сложность: O (n)
Способ № 5. Использование enumerate()
for i, item in enumerate(a):
print (item, end =' ')
#1 2 3 4
Временная сложность: O (n)
Способ № 6. Использование iterate()
Итерируемый объект – это такой объект, элементы которого можно перебрать. Например, последовательность. Итератор – это специальный объект, который перебирает элементы итерируемого объекта.
Если нам нужно извлечь какое-либо значение из списка или строки, то следует использовать индексы или срезы. Но если необходимо перебирать итерируемые объекты самых разных типов, то единственный универсальный и безопасный способ это сделать – использовать итераторы.
Пример использования итератора для просмотра списка
it = iter(a)
try:
while True:
x = next(it)
print(x, end=' ')
except StopIteration:
pass
#1 2 3 4
Временная сложность: O(n)
Для оценки производительности способов итерации по числовому списку будем использовать модуль timeit.
Измерения производятся с помощью класса Timer. Конструктор класса имеет следующий формат:
timeit.repeat(stmt, setup, number, repeat)
В параметрах указываются:
- stmt - код (в виде строки), время выполнения которого необходимо измерить
- setup - указывается код (в виде строки), который будет выполнен перед измерением времени выполнения кода в параметре stmt
- number – указывается количество повторений. Если параметр не задан, то по умолчанию равен 1_000_000
- Метод timeit.repeat вызывает метод timeit() указанное в параметре repeat количество раз и возвращает список значений.
Для оценки производительности способов итерации по числовому списку создадим список из 10 000 элементов перед измерением затраченного времени для каждого способа.
Каждый способ повторим 1000 раз, а затем создадим список из 5 запусков timeit и найдем минимальное значение в этом списке. Так мы получим оценочное время выполнения способов итерации по числовому списку.
Вот код:
import timeit
setup = """
a = [x for x in range(10_000) ]
# """
Способ_1 = """
for x in a:
z=x
"""
Способ_2 = """
for i in range(len(a)):
z = a[i]
"""
Способ_3 = """
n = len(a)
i = 0
while i<n:
z=a[i]
i+=1
"""
Способ_4 = """
[x for x in a]
"""
Способ_5 = """
for i, item in enumerate(a):
z=item
"""
Способ_6 = """
it = iter(a)
try:
while True:
z = next(it)
except StopIteration:
pass
"""
sp1 = min(timeit.repeat(stmt=Способ_1, setup=setup, number = 1_000, repeat=5))
sp2 = min(timeit.repeat(stmt=Способ_2, setup=setup, number = 1_000, repeat=5))
sp3 = min(timeit.repeat(stmt=Способ_3, setup=setup, number = 1_000, repeat=5))
sp4 = min(timeit.repeat(stmt=Способ_4, setup=setup, number = 1_000, repeat=5))
sp5 = min(timeit.repeat(stmt=Способ_5, setup=setup, number = 1_000, repeat=5))
sp6 = min(timeit.repeat(stmt=Способ_6, setup=setup, number = 1_000, repeat=5))
print(f" Способ № 1 = {sp1:.4f}")
print(f" Способ № 2 = {sp2:.4f}")
print(f" Способ № 3 = {sp3:.4f}")
print(f" Способ № 4 = {sp4:.4f}")
print(f" Способ № 5 = {sp5:.4f}")
print(f" Способ № 6 = {sp6:.4f}")
Результаты:
Способ № 1 = 0.0994
Способ № 2 = 0.2813
Способ № 3 = 0.4848
Способ № 4 = 0.1188
Способ № 5 = 0.3090
Способ № 6 = 0.2196
Как видно из результата цикл for x in a работает намного быстрее, чем все остальные, на втором месте использование генератора for x in a, и самый медленный способ это цикл с while.
Пример. Определить число в списке, равное значению 5.
a =[1,2,3,4,5,6,7,8,9,0]
d = 5
Способ №1. Использование цикла for
for i in range ( len(a) ):
if a[i] == d:
print(i, a[i])
break
else:
print ( "Число не найдено!"
# 4 5
Способ №2 Использование оператора вхождения in и метода index()
if d in a:
print(a.index(d),d )
else:
print ( "Число не найдено!" )
# 4 5
Способ №3 использование встроенной функции enumerate()
for i, item in enumerate(a):
if item ==5:
print(i, item)
break
else:
print("Число не найдено!")
# 4 5
Способ №4. Использование метода filter()
b = list(filter(lambda x: x == 5, a))
if b:
print(a.index(*b),*b)
else:
print("Элемент не найден.")
# 4 5
Способ №5. Использование цикла while и «барьерного» метода – выделяем дополнительный элемент списка – a[n] и заносим туда искомое значение. Это позволяет избавиться от проверки условия окончания цикла
a = [1,2,3,4,5,6,7,8,9,0,0]
d=5
n=10
a[n] = d
i=0
while (a[i]!=d):
i=i+1
if i == n:
print("Элемент не найден.")
else:
print(i, a[i])
# 4 5
Способ №6. Использование метода index()
Индекс s.index(x) возвращает первое вхождение элемента x в последовательность s
print("индекс первого вхождения =", a.index(5))
# индекс первого вхождения = 4
Способ №7. Использование метода count()
Метод s.count(x)возвращает количество вхождений элементов x в последовательность s.
print("кол-во вхожденией", a.count(5))
# кол-во вхождений 1
При выборе подходящего метода для поиска элементов в списках Python рекомендуется учитывать следующие факторы:
- Удобство использования: Некоторые методы, такие как цикл for, оператор вхождения x in s и метод index(), являются более простыми и понятными
- Гибкость: Некоторые методы позволяют выполнять дополнительные операции в процессе поиска, поэтому могут быть полезны такие методы, как enumerate() или filter()
Пример. Определить, есть ли в целочисленном списке четное число.
a =[1,2,3,4,5,6,7,8,9,0]
Все способы имеют временная сложность: O(n)
Способ № 1. Использование цикла for и range()
for i in range ( len(a) ):
if a[i]%2 == 0:
print ( "Первое четное число =", a[i])
break
else:
print ( "Нет четных чисел!" )
Первое четное число = 2
Способ № 2. Использование цикла for и оператора in
for x in a:
if x % 2 == 0:
print ( "Первое четное число =", x)
break
else:
print ( "Нет четных чисел!" )
Первое четное число = 2
Способ № 3. Использование генератора списка
b = [ x for x in a if x%2==0]
if b:
print("Первое четное число =", b[0])
else:
print("Нет четных чисел!")
Первое четное число = 2
Способ № 4. Использование функции enumerate()
for i, item in enumerate(a):
if item %2==0:
print( "Первое четное число =", item)
break
else:
print("Число не найдено!")
Первое четное число = 2
Способ № 5. Использование функции filter
b = list(filter(lambda x: x % 2 == 0, a))
if b:
print("Первое четное число = ",b[0])
else:
print("Элемент не найден.")
Первое четное число = 2


