Каков Большой-O из вложенного цикла, где количество повторений во внутреннем цикле определяется текущим повторением внешнего цикла?

Этот вопрос возникает ВСЕ ВРЕМЯ на SO. Это одна из первых вещей, с которой сталкиваются новые разработчики Swift.

Фон:

Swift использует концепцию «Опционы» для обработки значений, которые могут содержать значение, или нет. В других языках, таких как C, вы можете сохранить значение 0 в переменной, чтобы указать, что оно не содержит значения. Однако, что, если 0 является допустимым значением? Тогда вы можете использовать -1. Что, если -1 является допустимым значением? И так далее.

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

Вы помещаете вопросительный знак после типа, когда вы объявить переменную для обозначения (введите x или no value).

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

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

«!» оператор - оператор «разворота силы». Он говорит: «Поверь мне, я знаю, что делаю. Я гарантирую, что когда этот код будет запущен, переменная не будет содержать нуль». Если вы ошибаетесь, вы рухнете.

Если вы действительно не знаете, что делаете, избегайте «!». оператор разворачивания силы. Вероятно, это самый большой источник сбоев для начинающих программистов Swift.

Как бороться с опциями:

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

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

Ниже приведен пример необязательной привязки с нашим foo необязательным:

if let newFoo = foo //If let is called optional binding. {
  print("foo is not nil")
} else {
  print("foo is nil")
}

Примечание. что переменная, которую вы определяете при использовании дополнительного biding, существует (только «в области видимости») в теле оператора if.

В качестве альтернативы вы можете использовать инструкцию охраны, которая позволяет вам выйти из вашей функции если переменная равна nil:

func aFunc(foo: Int?) {
  guard let newFoo = input else { return }
  //For the rest of the function newFoo is a non-optional var
}

В Swift 2. Guard добавлены утверждения Guard. Guard позволяет сохранить «золотой путь» через ваш код и избегать постоянно растущих уровней вложенных ifs, которые иногда возникают из используя необязательную привязку «if let».

Существует также конструкция, называемая «оператор объединения ниль». Он принимает форму «optional_var ?? replacement_val». Он возвращает необязательную переменную с тем же типом, что и данные, содержащиеся в необязательном. Если опция содержит nil, она возвращает значение выражения после "??" символ.

Таким образом, вы можете использовать такой код:

let newFoo = foo ?? "nil" // "??" is the nil coalescing operator
print("foo = \(newFoo)")

Вы также можете использовать функцию try / catch или guard error, но, как правило, один из других методов выше - более чистый.

РЕДАКТИРОВАТЬ:

Еще один, немного более тонкий ключ с опциями - это «неявно разворачиваемые опционы». Когда мы объявляем foo, мы можем сказать:

var foo: String!

In в этом случае foo по-прежнему является необязательным, но вам не нужно разворачивать его, чтобы ссылаться на него. Это означает, что каждый раз, когда вы пытаетесь ссылаться на foo, вы вылетаете, если его нет.

Итак, этот код:

var foo: String!


let upperFoo = foo.capitalizedString

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

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

Нижняя строка. Когда вы впервые изучаете Swift, притворитесь, что символ «!» не является частью язык. Вероятно, вы получите int o проблема.

40
задан Lii 13 November 2016 в 18:00
поделиться

4 ответа

Да, это все еще O (n^2), это имеет меньший постоянный множитель, но это не влияет на нотацию O.

36
ответ дан Raul Agrait 27 November 2019 в 01:31
поделиться

Да. Вспомните определение Больших-O: O (f (n)) по определению говорит что время выполнения T (n) в‰ ¤ kf (n) для некоторой константы k. В этом случае количество шагов будет (n-1) + (n-2) +... +0 , который перестраивает к сумме 0 к n-1; это

T (n) = (n-1) ((n-1) +1)/2.

Перестроение это и Вы видите, что T (n) будет всегда составлять в‰ ¤1/2 (n²); по определению, таким образом T (n) = O (n²) .

26
ответ дан Charlie Martin 27 November 2019 в 01:31
поделиться

Это - N, в квадрате при игнорировании System.out.println. Если Вы предполагаете, что время, потраченное этим, будет линейно в его выводе (которым это не может быть, конечно), я подозреваю, что Вы заканчиваете с O ((N^2) * регистрируют N).

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

12
ответ дан Jon Skeet 27 November 2019 в 01:31
поделиться

Да, это был бы N, в квадрате. Фактическое количество шагов было бы сумма 1 к N, который является.5* (N - 1) ^2, если я не ошибаюсь. Большой O только принимает во внимание самую высокую экспоненту и никакие константы, и таким образом, это все еще N в квадрате.

3
ответ дан Charles Graham 27 November 2019 в 01:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: