1 2 пример: Реши пример 1/2 + 3/8

2

Содержание

ЕСЛИ (функция ЕСЛИ) — Служба поддержки Майкрософт

Функция ЕСЛИ — одна из самых популярных функций в Excel. Она позволяет выполнять логические сравнения значений и ожидаемых результатов.

Поэтому у функции ЕСЛИ возможны два результата. Первый результат возвращается в случае, если сравнение истинно, второй — если сравнение ложно.

Например, функция =ЕСЛИ(C2=»Да»;1;2) означает следующее: ЕСЛИ(С2=»Да», то вернуть 1, в противном случае вернуть 2).

Функция ЕСЛИ, одна из логических функций, служит для возвращения разных значений в зависимости от того, соблюдается ли условие.

ЕСЛИ(лог_выражение; значение_если_истина; [значение_если_ложь])

Например:

Имя аргумента

Описание

лог_выражение    (обязательно)

Условие, которое нужно проверить.

значение_если_истина    (обязательно)

Значение, которое должно возвращаться, если лог_выражение имеет значение ИСТИНА.

значение_если_ложь    (необязательно)

Значение, которое должно возвращаться, если лог_выражение

имеет значение ЛОЖЬ.

Простые примеры функции ЕСЛИ

  • =ЕСЛИ(C2=»Да»;1;2)

В примере выше ячейка D2 содержит формулу: ЕСЛИ(C2 = Да, то вернуть 1, в противном случае вернуть 2)

В этом примере ячейка D2 содержит формулу: ЕСЛИ(C2 = 1, то вернуть текст «Да», в противном случае вернуть текст «Нет»). Как видите, функцию ЕСЛИ можно использовать для сравнения и текста, и значений. А еще с ее помощью можно оценивать ошибки. Вы можете не только проверять, равно ли одно значение другому, возвращая один результат, но и использовать математические операторы и выполнять дополнительные вычисления в зависимости от условий. Для выполнения нескольких сравнений можно использовать несколько вложенных функций ЕСЛИ.

В примере выше функция ЕСЛИ в ячейке D2 означает: ЕСЛИ(C2 больше B2, то вернуть текст «Превышение бюджета», в противном случае вернуть текст «В пределах бюджета»)

На рисунке выше мы возвращаем не текст, а результат математического вычисления. Формула в ячейке E2 означает: ЕСЛИ(значение «Фактические» больше значения «Плановые», то вычесть сумму «Плановые» из суммы «Фактические», в противном случае ничего не возвращать).

В этом примере формула в ячейке F7 означает: ЕСЛИ(E7 = «Да», то вычислить общую сумму в ячейке F5 и умножить на 8,25 %, в противном случае налога с продажи нет, поэтому вернуть 0)

Примечание: Если вы используете текст в формулах, заключайте его в кавычки (пример: «Текст»).

Единственное исключение — слова ИСТИНА и ЛОЖЬ, которые Excel распознает автоматически.

Распространенные неполадки

Проблема

Возможная причина

0 (ноль) в ячейке

Не указан аргумент значение_если_истина или значение_если_ложь. Чтобы возвращать правильное значение, добавьте текст двух аргументов или значение ИСТИНА/ЛОЖЬ.

#ИМЯ? в ячейке

Как правило, это указывает на ошибку в формуле.

Дополнительные сведения

Вы всегда можете задать вопрос специалисту Excel Tech Community или попросить помощи в сообществе Answers community.

См. также

Функция ЕСЛИ — вложенные формулы и типовые ошибки

Функция УСЛОВИЯ

Использование ЕСЛИ с функциями И, ИЛИ и НЕ

СЧЁТЕСЛИ

Рекомендации, позволяющие избежать появления неработающих формул

Общие сведения о формулах в Excel

Python Set (с примерами)

В этом уроке мы изучим Set и его различные операции в Python с помощью примеров.

Набор — это набор уникальных данных. То есть элементы набора не могут повторяться. Например,

Предположим, мы хотим сохранить информацию о идентификаторах учащихся . Поскольку студенческих билетов не могут дублироваться, мы можем использовать набор.

Элементы набора Python

Создание набора в Python

В Python мы создаем наборы, помещая все элементы в фигурные скобки {} , разделенные запятой.

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

Давайте посмотрим пример,

 # создаем набор целочисленного типа
student_id = {112, 114, 116, 118, 115}
print('Идентификатор студента:', student_id)
# создаем набор строкового типа
vowel_letters = {'а', 'е', 'и', 'о', 'у'}
print('Гласные буквы:', vowel_letters)
# создаем набор смешанных типов данных
mix_set = {'Привет', 101, -2, 'Пока'}
print('Набор смешанных типов данных:',mixed_set) 

Выход

  Студенческий идентификатор: {112, 114, 115, 116, 118}
Гласные буквы: {'у', 'а', 'е', 'и', 'о'}
Набор смешанных типов данных: {'Hello', 'Bye', 101, -2} 

В приведенном выше примере мы создали различные типы наборов, поместив все элементы в фигурные скобки {} .

Примечание: При выполнении этого кода вы можете получить вывод в другом порядке. Это потому, что набор не имеет определенного порядка.


Создать пустой набор в Python

Создать пустой набор немного сложно. Пустые фигурные скобки {} сделают пустой словарь в Python.

Чтобы создать набор без каких-либо элементов, мы используем функцию set() без каких-либо аргументов. Например,

 # создать пустой набор
пустой_набор = набор ()
# создать пустой словарь
пустой_словарь = {}
# проверить тип данных empty_set
print('Тип данных empty_set:', type(empty_set))
# проверить тип данных Dictionary_Set
print('Тип данных empty_dictionary', type(empty_dictionary)) 

Выход

  Тип данных empty_set: <класс 'набор'>
Тип данных empty_dictionary   

Здесь

  • empty_set — пустой набор, созданный с помощью set()
  • empty_dictionary — пустой словарь, созданный с помощью {}

Наконец, мы использовали функцию type() , чтобы узнать, какой класс empty_set и empty_dictionary принадлежит.


Повторяющиеся предметы в наборе

Посмотрим, что произойдет, если мы попытаемся включить в набор повторяющиеся предметы.

 числа = {2, 4, 6, 6, 2, 8}
print(numbers) # {8, 2, 4, 6} 

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


Добавление и обновление элементов набора в Python

Наборы изменяемы. Однако, поскольку они неупорядочены, индексация не имеет смысла.

Мы не можем получить доступ к элементу набора или изменить его с помощью индексации или нарезки. Установить тип данных не поддерживает его.

Добавление элементов в набор в Python

В Python мы используем метод add() для добавления элемента в набор. Например,

 числа = {21, 34, 54, 12}
print('Исходный набор:',числа)
# используя метод add()
числа.добавить(32)
print('Обновленный набор:', числа) 

Вывод

  Исходный набор: {34, 12, 21, 54}
Обновленный набор: {32, 34, 12, 21, 54}  

В приведенном выше примере мы создали набор с именем чисел . Обратите внимание на строку 9.0003

 numbers.add(32) 

Здесь add() добавляет 32 к нашему набору.

Обновить набор Python

Метод update() используется для обновления набора элементами других типов коллекций (списки, кортежи, наборы и т. д.). Например,

 компании = {'Lacoste', 'Ralph Lauren'}
tech_companies = ['яблоко', 'гугл', 'яблоко']
компании.обновление(технические_компании)
печать (компании)
# Вывод: {'google', 'apple', 'Lacoste', 'Ralph Lauren'} 

Здесь все уникальные элементы

tech_companies добавлены в набор компаний .


Удаление элемента из набора

Мы используем метод discard() для удаления указанного элемента из набора. Например,

 языка = {'Swift', 'Java', 'Python'}
print('Исходный набор:',языки)
# удалить 'Java' из набора
removeValue = languages.discard('Java')
print('Установить после удаления():', языки) 

Вывод

  Исходный набор: {'Python', 'Swift', 'Java'}
Установить после удаления(): {'Python', 'Swift'}  

Здесь мы использовали метод discard() для удаления 'Java' из набора языков . , any() , sorted() , sum() и т. д. обычно используются с наборами для выполнения различных задач.

Функция Описание
все() Возвращает True , если все элементы набора истинны (или если набор пуст).
любой() Возвращает True , если любой элемент набора истинен. Если набор пуст, возвращает False .
перечислить() Возвращает перечисляемый объект. Он содержит индекс и значение для всех элементов набора в виде пары.
лен() Возвращает длину (количество элементов) в наборе.
макс() Возвращает самый большой элемент в наборе.
мин() Возвращает наименьший элемент в наборе.
отсортировано() Возвращает новый отсортированный список из элементов набора (сам набор не сортируется).
сумма() Возвращает сумму всех элементов набора.

Перебор набора в Python

 фрукты = {"Яблоко", "Персик", "Манго"}
# цикл for для доступа к каждому фрукту
для фруктов во фруктах:
    печать (фрукты) 

Вывод

  Манго
Персик
Apple  

Найти количество элементов набора

Мы можем использовать метод len() , чтобы найти количество элементов, присутствующих в наборе. Например,

 четные_числа = {2,4,6,8}
print('Установить:',even_numbers)
# найти количество элементов
print('Всего элементов:', len(even_numbers)) 

Выход

  Комплект: {8, 2, 4, 6}
Всего элементов: 4  

Здесь мы использовали метод len() , чтобы найти количество элементов, присутствующих в наборе.


Python Set Operations

Python Set предоставляет различные встроенные методы для выполнения математических операций над множествами, таких как объединение, пересечение, вычитание и симметричная разность.

Объединение двух комплектов

Объединение двух комплектов А и B включает в себя все элементы набора A и B .

Set Union в Python

Мы используем | Оператор или метод union() для выполнения операции set union. Например,

 # первый набор
А = {1, 3, 5}
# второй набор
Б = {0, 2, 4}
# выполнить операцию объединения, используя |
print('Объединение с использованием |:', A | B)
# выполнить операцию объединения с помощью union()
print('Объединение с использованием union():', A.union(B)) 

Вывод

  Объединение с использованием |: {0, 1, 2, 3, 4, 5}
Объединение с использованием union(): {0, 1, 2, 3, 4, 5}  

Примечание : A|B и union() эквивалентно операции набора A ⋃ B .


Пересечение набора

Пересечение двух наборов A и B включает общие элементы между наборами A и B .

Установить пересечение в Python

В Python мы используем операторы и или метод пересечения() для выполнения операции установки пересечения. Например,

 # первый набор
А = {1, 3, 5}
# второй набор
В = {1, 2, 3}
# выполнить операцию пересечения с помощью &
print('Пересечение с использованием &:', A и B)
# выполнить операцию пересечения с помощью функции пересечения()
print('Пересечение с использованием пересечения():', A.intersection(B)) 

Вывод

  Пересечение с использованием &: {1, 3}
Пересечение с использованием cross(): {1, 3}  

Примечание : A&B и пересечение() эквивалентно A ⋂ B установка операции.


Разница между двумя наборами

Разница между двумя наборами A и B включает элементы набора A , которых нет в наборе B .

Установить разницу в Python

Мы используем оператор - или метод разница() для определения разницы между двумя наборами. Например,

 # первый набор
А = {2, 3, 5}
# второй набор
В = {1, 2, 6}
# выполнить операцию разности с помощью &
print('Разница с использованием &:', A - B)
# выполнить операцию разности, используя разность()
print('Разница с использованием разницы():', A.difference(B)) 

Выход

  Разница с использованием &: {3, 5}
Разность с использованием разности(): {3, 5}  

Примечание : A - B и A.difference(B) эквивалентно операции набора A - B .


Набор Симметричная разность

Симметричная разность между двумя наборами A и B включает все элементы A и B без общих элементов.

Установить симметричную разницу в Python 9: {1, 3, 5, 6} использование симметричной_разности(): {1, 3, 5, 6}

Проверка равенства двух наборов

Мы можем использовать оператор == , чтобы проверить, равны ли два набора или нет. Например,

 # первый набор
А = {1, 3, 5}
# второй набор
В = {3, 5, 1}
# выполнить операцию разности с помощью &
если А == В:
    print('Набор A и набор B равны')
еще:
    print('Set A и Set B не равны') 

Вывод

  Набор A и набор B равны  

В приведенном выше примере A и B имеют одинаковые элементы, поэтому условие

, если A == B 

, оценивается как True . Следовательно, оператор печатает («Набор A и набор B равны») внутри , если выполняется.


Другие методы установки Python

Существует много методов установки, некоторые из которых мы уже использовали выше. Вот список всех методов, которые доступны с установленными объектами:

.
Метод Описание
добавить() Добавляет элемент в набор
очистить() Удаляет все элементы из набора
копирование() Возвращает копию набора
разница() Возвращает разницу двух или более наборов в виде нового набора
разность_обновление() Удаляет все элементы другого набора из этого набора
отбросить() Удаляет элемент из набора, если он является членом. (Ничего не делать, если элемента нет в наборе)
пересечение() Возвращает пересечение двух наборов как новый набор
cross_update() Обновляет набор пересечением себя и другого
является непересекающимся() Возвращает Истинно , если два набора имеют нулевое пересечение
issubset() Возвращает True , если другой набор содержит этот набор
issuperset () Возвращает True , если этот набор содержит другой набор
поп() Удаляет и возвращает произвольный элемент набора. Вызывает KeyError , если набор пуст
удалить() Удаляет элемент из набора. Если элемент не является членом, вызывает ошибку KeyError
симметричная_разность() Возвращает симметричную разность двух наборов как новый набор
симметричная_разница_обновление() Обновляет набор с симметричной разностью себя и другого
объединение() Возвращает объединение наборов в новый набор
обновление() Обновляет набор объединением себя и других

Понимание временной сложности на примерах Python | Келвин Солтон из Прадо.

Таблица сложности Big-O: http://bigocheatsheet.com/

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

В этом посте мы узнаем немного больше о временной сложности, нотации Big-O и почему нам нужно беспокоиться об этом при разработке алгоритмов.

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

Давайте начнем понимать, что такое вычислительная сложность.

Сложность вычислений — это область информатики, которая анализирует алгоритмы на основе количества ресурсов, необходимых для их выполнения . Количество необходимых ресурсов варьируется в зависимости от размера входных данных, поэтому сложность обычно выражается как функция n , где n — размер ввода.

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

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

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

При анализе временной сложности алгоритма мы можем найти три случая: лучший случай , средний случай и в худшем случае . Давайте поймем, что это значит.

Предположим, у нас есть следующий несортированный список [1, 5, 3, 9, 2, 4, 6, 7, 8] и нам нужно найти индекс значения в этом списке, используя линейный поиск.

  • лучший случай : это сложность решения задачи для наилучшего ввода. В нашем примере наилучшим вариантом будет поиск значения 1. Поскольку это первое значение списка, оно будет найдено на первой итерации.
  • средний случай : это средняя сложность решения задачи. Эта сложность определяется относительно распределения значений во входных данных. Возможно, это не лучший пример, но, основываясь на нашей выборке, мы могли бы сказать, что средний случай будет, когда мы ищем какое-то значение в «середине» списка, например, значение 2.
  • наихудший случай : это сложность решения задачи для наихудшего входа размера n. В нашем примере наихудшим случаем будет поиск значения 8, которое является последним элементом в списке.

Обычно при описании временной сложности алгоритма говорят о наихудшем случае.

Хорошо, но как описать временную сложность алгоритма?

Мы используем математическую нотацию Big-O.

Нотация Big-O , иногда называемая «асимптотической нотацией», — это математическая нотация, описывающая предельное поведение функции , когда аргумент стремится к определенному значению или к бесконечности.

В компьютерных науках нотация Big-O используется для классификации алгоритмов в соответствии с тем, как их требования к времени выполнения или объему памяти растут по мере увеличения размера входных данных ( н ) растет. Это обозначение характеризует функции в соответствии с их скоростью роста: разные функции с одинаковой скоростью роста могут быть представлены с использованием одной и той же записи O.

Давайте рассмотрим некоторые распространенные временные сложности, описанные в нотации Big-O.

Таблица общих временных сложностей

Ниже приведены наиболее распространенные временные сложности, выраженные с помощью нотации Big-O: ═════════════╗
Имя ║ 9n) ║
╠══════════════════╬═════════════════╣
║ Факторное время ║ O (n ! изучите эти общие временные сложности, но есть и другие временные сложности, которые вы можете изучить позже.

Как уже было сказано, мы обычно используем нотацию Big-O для описания временной сложности алгоритмов. Формальное определение нотации связано с большим количеством математических вычислений, но неформально мы можем предположить, что нотация Big-O дает нам приблизительное время выполнения алгоритма в худшем случае. При использовании нотации Big-O мы описываем эффективность алгоритма на основе увеличения размера входных данных ( N ). Например, если вход представляет собой строку, n будет длиной строки. Если это список, n будет длиной списка и так далее.

Теперь давайте рассмотрим каждую из этих распространенных временных сложностей и рассмотрим несколько примеров алгоритмов. Обратите внимание, что я пытался следовать следующему подходу: представить небольшое описание, показать простой и понятный пример и показать более сложный пример (обычно из реальной проблемы).

Постоянное время — O(1)

Говорят, что алгоритм имеет постоянное время, когда он не зависит от входных данных ( n ). Независимо от размера входных данных, время выполнения всегда будет одинаковым. Например:

 если a > b: 
вернуть True
иначе:
вернуть False

Теперь давайте посмотрим на функцию get_first которая возвращает первый элемент списка:

 def get_first(data): 
вернуть данные[0]

, если __name__ == '__main__':
data = [1, 2, 9, 8, 3, 4, 7, 6, 5]
print(get_first(data))

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

Алгоритм с постоянной временной сложностью превосходен, поскольку нам не нужно беспокоиться о размере входных данных.

Логарифмическое время — O(log n)

Говорят, что алгоритм имеет логарифмическую временную сложность, когда он уменьшает размер входных данных на каждом шаге (не нужно просматривать все значения входных данных) , например:

 для индекса в диапазоне (0, len(data), 3): 
print(data[index])

Алгоритмы с логарифмической временной сложностью обычно встречаются в операциях с бинарными деревьями или при использовании бинарного поиска. Давайте рассмотрим пример бинарного поиска, где нам нужно найти позицию элемента в отсортированном списке:

 def binary_search(data, value): 
n = len(data)
left = 0
right = n - 1
, в то время как слева <= справа:
посередине = (слева + справа) // 2
, если значение < data[middle]:
right = middle - 1
elif value > data[middle]:
left = middle + 1
else:
return middle
поднять ValueError('Значение отсутствует в списке')

if __name__ == '__main__':
data = [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(binary_search(data, 8))

Шаги бинарного поиска:

  • Вычислить середину списка.
  • Если искомое значение ниже значения в середине списка, установите новую правую границу.
  • Если искомое значение выше, чем значение в середине списка, установите новую левую границу.
  • Если искомое значение равно значению в середине списка, вернуть середину (индекс).
  • Повторяйте описанные выше шаги, пока не будет найдено значение или левая граница не будет равна или выше правой границы.

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

Линейное время — O(n)

Говорят, что алгоритм имеет линейную временную сложность, когда время выполнения увеличивается не более чем линейно с размером входных данных. Это наилучшая возможная временная сложность, когда алгоритм должен проверять все значения во входных данных. Например:

 для значения в данных: 
print(value)

Давайте рассмотрим пример линейного поиска, где нам нужно найти позицию элемента в несортированном списке:

 def linear_search(data , значение): 
для индекса в диапазоне (длина (данные)):
, если значение == данные [индекс]:
вернуть индекс
поднять ValueError («Значение не найдено в списке»)

, если __name__ == '__main__':
данные = [1, 2, 9, 8, 3, 4 , 7, 6, 5]
print(linear_search(data, 7))

Обратите внимание, что в этом примере нам нужно просмотреть все значения в списке, чтобы найти искомое значение.

Квазилинейное время — O(n log n)

Говорят, что алгоритм имеет квазилинейную временную сложность, когда каждая операция во входных данных имеет логарифмическую временную сложность. Это обычно встречается в алгоритмах сортировки (например, сортировка слиянием, сортировка по времени, сортировка по пирамиде).

Например: для каждого значения в данных1 ( O(n) ) используйте двоичный поиск ( O(log n) ) для поиска того же значения в данных2.

 для значения в data1: 
result.append(binary_search(data2, value))

Другой, более сложный пример, можно найти в алгоритме Mergesort. Сортировка слиянием — это эффективный алгоритм сортировки общего назначения на основе сравнения с квазилинейной временной сложностью. Рассмотрим пример:

 def merge_sort(data): 
if len(data) <= 1:
return

mid = len(data) // 2
left_data = data[:mid]
right_data = data[mid:]

merge_sort(left_data)
merge_sort(right_data)

left_index = 0
right_index = 0_index = 0

в то время как left_index < len(left_data) и right_index < len(right_data):
if left_data[left_index] < right_data[right_index]:
data[data_index] = left_data[left_index]
left_index += 1
else:
данные[индекс_данных] = правильные_данные[правый_индекс]
right_index += 1
data_index += 1

if left_index < len(left_data):
del data[data_index:]
data += left_data[left_index:]
elif right_index < len(right_data):
del data[data_index :]
data += right_data[right_index:]

if __name__ == '__main__':
data = [9, 1, 7, 6, 2, 8, 5, 3, 4, 0]
merge_sort(data)
print(data)

На следующем изображении показаны шаги, выполняемые алгоритмом сортировки слиянием.

Пример сортировки слиянием: https://en.wikipedia.org/wiki/Merge_sort

Обратите внимание, что в этом примере сортировка выполняется на месте.

Квадратичное время — O(n²)

Говорят, что алгоритм имеет квадратичную временную сложность, когда ему необходимо выполнять операцию линейного времени для каждого значения во входных данных, например:

 для x в данных: 
для y в данных:
print(x, y)

Пузырьковая сортировка — отличный пример квадратичной временной сложности, поскольку для каждого значения необходимо сравнить со всеми другими значениями в списке, давайте посмотрим на пример: 9n)

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

На примере Вики Лай:

В криптографии атака грубой силы может систематически проверять все возможные элементы пароля путем перебора подмножеств. Используя для этого экспоненциальный алгоритм, становится невероятно ресурсоемким взлом длинного пароля по сравнению с более коротким. Это одна из причин, по которой длинный пароль считается более безопасным, чем короткий.

Другим примером алгоритма экспоненциального времени является рекурсивный расчет чисел Фибоначчи: )

Если вы не знаете, что такое рекурсивная функция, давайте быстро поясним: рекурсивная функция может быть описана как функция, которая вызывает сама себя в определенных условиях. Как вы, возможно, заметили, временную сложность рекурсивных функций определить немного сложнее, поскольку она зависит от того, сколько раз вызывается функция, и от временной сложности одного вызова функции.

Это имеет больше смысла, если мы посмотрим на дерево рекурсии. Следующее дерево рекурсии было сгенерировано алгоритмом Фибоначчи с использованием n = 4 :

Дерево рекурсии Фибоначчи (4): https://visualgo.net/bn/recursion

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

Теперь посмотрите, как растет дерево рекурсии, просто увеличивая n до 6:

Дерево рекурсии Фибоначчи(6): https://visualgo.net/bn/recursion

Вы можете найти более полное объяснение временной сложности рекурсивного алгоритма Фибоначчи здесь, на StackOverflow.

Факториал — O(n!)

Говорят, что алгоритм имеет факториальную временную сложность, когда он увеличивается факториально в зависимости от размера входных данных, например:

 2! = 2 х 1 = 2 
3! = 3 х 2 х 1 = 6
4! = 4 х 3 х 2 х 1 = 24
5! = 5 х 4 х 3 х 2 х 1 = 120
6! = 6 х 5 х 4 х 3 х 2 х 1 = 720
7! = 7 х 6 х 5 х 4 х 3 х 2 х 1 = 5,040
8! = 8 х 7 х 6 х 5 х 4 х 3 х 2 х 1 = 40,320

Как вы можете видеть, он растет очень быстро, даже для ввода небольшого размера.

Отличным примером алгоритма с факториальной временной сложностью является алгоритм кучи, который используется для генерации всех возможных перестановок n объектов.

Согласно Википедии:

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

Рассмотрим пример:

 def heap_permutation(data, n): 
if n == 1:
print(data)
return

for i in range(n):
heap_permutation(data, n) - 1)
, если n % 2 == 0:
data[i], data[n-1] = data[n-1], data[i]
иначе:
data[0], data[n-1 ] = data[n-1], data[0]

if __name__ == '__main__':
data = [1, 2, 3]
heap_permutation(data, len(data))

Результат будет :

 [1, 2, 3] 
[2, 1, 3]
[3, 1, 2]
[1, 3, 2]
[2, 3, 1]
[3, 2, 1]

Обратите внимание, что он будет расти факторным образом в зависимости от размера входных данных, поэтому можно сказать, что алгоритм имеет факториальную временную сложность O(n!).

Другим прекрасным примером является задача о коммивояжере.

Важно отметить, что при анализе временной сложности алгоритма с несколькими операциями нам необходимо описать алгоритм на основе наибольшей сложности среди всех операций. Например:

 def my_function(data): 
first_element = data[0]

для значения в данных:
print(value)

для x в данных:
для y в данных:
print(x, y)

Четный что операции в «my_function» не имеют смысла, мы можем видеть, что он имеет несколько временных сложностей: O (1) + O (n) + O (n²). Итак, при увеличении размера входных данных узким местом этого алгоритма будет операция, выполняющая O(n²). Исходя из этого, мы можем описать временную сложность этого алгоритма как O(n²).

Чтобы облегчить вам жизнь, здесь вы можете найти таблицу с временной сложностью операций в наиболее распространенных структурах данных.

Общие операции со структурой данных: http://bigocheatsheet.com/

Вот еще один лист с временной сложностью наиболее распространенных алгоритмов сортировки.

Алгоритмы сортировки массивов: http://bigocheatsheet.com/

Если после прочтения всей этой истории у вас все еще остались сомнения относительно важности знания временной сложности и нотации Big-O, давайте проясним некоторые моменты.

Даже при работе с современными языками, такими как Python, которые предоставляют встроенные функции, такие как алгоритмы сортировки, когда-нибудь вам, вероятно, понадобится реализовать алгоритм для выполнения какой-либо операции с определенным объемом данных. Изучая временную сложность, вы поймете важную концепцию эффективности и сможете найти узкие места в своем коде, которые следует улучшить, в основном при работе с огромными наборами данных.

Кроме того, если вы планируете подать заявку на должность инженера-программиста в крупной компании, такой как Google, Facebook, Twitter и Amazon, вы должны быть готовы ответить на вопросы о временной сложности, используя нотацию Big-O.

Спасибо, что прочитали эту историю. Надеюсь, вы узнали немного больше о временной сложности и нотации Big-O.

admin

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *