Хобрук: Ваш путь к мастерству в программировании

Временная сложность против пространственной сложности

Я пытаюсь понять разницу между временной и пространственной сложностью из короткого алгоритма. Этот код принимает список/массив и возвращает одно число, которое встречается нечетное количество раз. В Питоне:

def foo(array_of_ints):
    hash_table = dict()
    for i in array_of_ints:
        hash_table[i] = hash_table.setdefault(i, 0) + 1
    for key, value in hash_table.items():
        if value%2 != 0:
            return key

Есть два цикла for, которые перебирают длину массива. Но первый цикл просто создает хеш-таблицу/словарь в памяти. Итак, временная сложность O(n^2), потому что мы дважды перебираем массив длины n, или временная сложность и пространственная сложность равны O(n), поскольку первый цикл просто создает новую структуру данных в памяти?


  • повторение N дважды равно O (2 * N) = O (N), а не N ^ 2 12.11.2015
  • Не ответ, но алгоритм можно улучшить до O(1) пробела, просто объединив XOR со всеми целыми числами и вернув результат. 12.11.2015
  • Это домашнее задание? 12.11.2015
  • вы можете использовать hash_table = collections.Counter(array_of_ints). @ user2357112: ты имеешь в виду return reduce(lambda acc, i: acc ^ i, array_of_ints)? 12.11.2015
  • @ J.F.Sebastian: Довольно много. Все элементы, которые появляются четное количество раз, отменяются. 12.11.2015

Ответы:


1

Как и временная сложность O (n ^ 2), потому что мы дважды перебираем массив длины n.

Временная сложность вашего кода не O(N²).

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

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

Это означает, что ваша функция может перебирать одну и ту же коллекцию 5 раз, и это будет O(5N), что по-прежнему равно O(N).

Но как тогда получить O(N²)? Вы начнете рассматривать их как начало вложения циклов друг в друга.

Пример A - O(N)

def linear(integers):
    # no nesting
    for i in integers: print(i)
    for i in integers: print(i+1)

Пример B - O(N²)

def quadratic(integers):
    # notice double nesting
    for i in integers:
        for j in integers:
            print(i+j)

Пример C - O(N³)

def cubed(integers):
    # notice triple-nesting
    for i in integers:
        for j in integers:
            for k in integers:
                print(i+j+k)

Вы найдете примеры O(N³) алгоритмов, если работаете с матрицами, по крайней мере, если используете наивные реализации. Если вам непонятно, это называется асимптотическая запись.

Также обратите внимание, что нотация Big-Oh выражает верхнюю границу времени работы алгоритма. Это означает, что это мера наихудшего сценария.

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

или временная и пространственная сложность > O(n), поскольку первый цикл просто создает новую структуру данных в памяти?

То, что делает цикл, само по себе не имеет отношения к измерению в этом случае. Что важно, так это операция, которая здесь доминирует, а именно сравнения и приращения, которые заставляют циклы работать. Например, value % 2 != 0 — это операция с постоянным временем¹ или O(1), и она не окажет существенного влияния на время выполнения вашего кода.

Так что же такое космическая сложность?

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

Если каждое значение уникально, то для каждого значения будет добавлена ​​пара ключ/значение. Поэтому для алгоритма требуется O(N) места.

Обратите внимание, что это может быть меньше, но нотация big-O сообщает верхнюю границу.

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


¹Это предполагает, что мы определили арифметические операции, такие как +, -, /, *, % и т. д., как базовые операции, что обычно и делается.

12.11.2015
  • Так что же такое космическая сложность? 12.11.2015
  • @kevin: Если вы считаете, что используемое пространство является функцией размера ввода, как это выглядит для вас? Это та же концепция, но применительно к пространству, а не к времени работы. 12.11.2015

  • 2

    В большой нотации O 2n и n не считаются разными, поэтому алгоритм ведет себя O(n). Чтобы иметь поведение O(n^2), ваш алгоритм должен был бы пройти/построить весь массив один раз для каждого элемента в массиве. Другими словами, вам понадобятся вложенные циклы для достижения O(n^2).

    12.11.2015

    3

    И временная, и пространственная сложность составляют O(n).

    12.11.2015
  • Может ли downvoter сообщить мне, почему за мой ответ проголосовали? 16.11.2015
  • Ответу не хватает объяснения, и он не очень полезен для тех, кто читает этот вопрос. 16.11.2015
  • Новые материалы

    Расистский и сексистский робот, обученный в Интернете
    Его ИИ основан на предвзятых данных, которые создают предрассудки. Он словно переходит из одного эпизода в другой из серии Черное зеркало , а вместо этого представляет собой хронику..

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

    Декларативное и функциональное программирование в стиле LINQ с использованием JavaScript с использованием каррирования и генератора ...
    LINQ - одна из лучших функций C #, которая обеспечивает элегантный способ написания кода декларативного и функционального стиля, который легко читать и понимать. Благодаря таким функциям ES6,..

    Структуры данных в C ++ - Часть 1
    Реализация общих структур данных в C ++ C ++ - это расширение языка программирования C, которое поддерживает создание классов, поэтому оно известно как C с классами . Он используется для..

    Как я опубликовал свое первое приложение в App Store в 13 лет
    Как все началось Все началось три года назад летом после моего четвертого класса в начальной школе. Для меня, четвертого класса, лето кажется бесконечным, пока оно не закончится, и мой отец..

    Что в лицо
    Очерк о возвращении физиогномики и о том, почему мы должны это приветствовать. История начинается со странной науки. Р. Тора Бьорнсдоттир, Николас О. Рул. Видимость социального класса по..

    Почему шаблоны проектирования и почему нет?
    Сложность — мать всех проблем в программировании. Программное обеспечение должно быть разработано с точки зрения того, кто его поддерживает, а не того, кто его пишет, потому что программное..


    © 2024 hobruk.ru, Хобрук: Ваш путь к мастерству в программировании