Что подразумевается под «в постоянное время»? - PullRequest
25 голосов
/ 02 декабря 2010

Я работаю программистом, но не обладаю знаниями в области компьютерных наук, поэтому в последнее время я следую вместе с превосходным введением MIT OpenCourseWare в области компьютерных наук и программирования.В ходе которого задается вопрос: «Будет ли любая программа, написанная с использованием только определений функций и вызовов, основных арифметических операторов, присваиваний и условных выражений, выполняться в постоянное время?»

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

Кажется, что я просто не понимаю последствий «в постоянном времени».То, как я изобразил значение, звучало так, словно это означало, что простая операция займет известное количество времени для завершения.Я согласен с тем, что рекурсия может привести к тому, что ваша программа будет работать вечно, но разве отдельные операции все еще не занимают ограниченное и измеримое количество времени каждая ... даже если их сейчас бесконечное количество?Или же ответ просто означает, что нельзя сказать, что две бесконечно рекурсивные программы могут занимать одинаковое количество времени для запуска?

Если кто-то может дать мне авторитетное определение «в постоянном времени» и последствия этогоБуду очень признателен!

Ответы [ 8 ]

35 голосов
/ 02 декабря 2010

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

Сравните это, скажем, с линейным временем (для некоторого ввода n - который часто будет размером входных данных, а не прямым значением) - что означает, что верхняя граница время может быть выражено как mn + k для некоторых значений m и k.

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

int foo(int n)
{
    if (n == 0)
    {
        return 0;
    }
    int j = n + 1;
    int k = j * 2;
    return k;
}

Это делает больше работы в случае, когда n не равен нулю, чем в случае, когда он равен нулю. Однако это все еще постоянное время - самое большее , он собирается сделать одно сравнение, одно сложение и одно умножение.

Теперь сравните это с рекурсивной функцией:

public int foo(int n)
{
    if (n <= 1)
    {
        return 1;
    }
    return n * foo(n - 1);
}

Это будет повторяться n раз - поэтому оно линейно в n. Однако, вы можете стать намного хуже линейного. Рассмотрим этот метод для вычисления числа Фибоначчи:

public int fib(int n)
{
    if (n == 0)
    {
        return 0;
    }
    if (n == 1)
    {
        return 1;
    }
    return fib(n - 2) + fib(n - 1);
}

Это не выглядит намного хуже, чем в предыдущей версии - но теперь это экспоненциально (верхняя граница легче всего выражается в терминах как O (2 n) ). Хотя он все еще использует только простые сравнения, сложения и вызовы функций.

14 голосов
/ 02 декабря 2010

«Постоянное время» означает, что операция будет выполняться за определенный промежуток времени (или объем памяти - это часто измеряется) независимо от размера ввода.Обычно вы выбираете переменную (давайте используем n), чтобы указать размер ввода.

O(1) - постоянное время - время работы не зависит от n

O(n) -линейное время - время работы линейно пропорционально до n

O(n^2) - квадратичное время - время работы пропорционально квадрату n

Это всего лишь несколько примеров;возможности безграничны.См. Статью вики о сложность

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

int n = // some value
doSomething
doSomething
doSomething

Примечаниекак это три что-то в длину, независимо от того, что n.O(1)

int n = // some value
def f(n):
    if n == 0 return
    doSomething
    f(n-1)
f(n)

Теперь мы запускаем что-то для каждого значения 0..n (линейное время, O(n))

И мы можем получить немноговеселья -

int n = //some value
def f(n):
    if n == 0 return
    doSomething
    f(n-1)
    f(n-1)

Сколько времени здесь?(т.е. сколько что-то мы выполним?):)

8 голосов
/ 02 декабря 2010

«Постоянное время» имеет то же значение, что и «O (1)», что не означает, что алгоритм работает за фиксированное количество времени, это просто означает, что оно не пропорционально к длине / размеру / величине входа. т. е. для любого ввода он может быть рассчитан за то же время (даже если это время действительно велико).

4 голосов
/ 02 декабря 2010

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

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

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

2 голосов
/ 02 декабря 2010

Постоянное время здесь означает, что оно не зависит от количества входов (не от самого входа), и если вам не разрешено или нет, единственный способ заставить его зависеть от количества входов - это условные выражения и рекурсия. Хотя вы можете утверждать, что рекурсия не является необходимой с некоторыми дискуссионными решениями. Например. (в С)

if(ReadInput()) DoSomeThing();
if(ReadInput()) DoSomeThing();
if(ReadInput()) DoSomeThing();
if(ReadInput()) DoSomeThing();
1 голос
/ 02 декабря 2010

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

Рассмотрим факториальную функцию как контрпример. Скажем, факториал 5 рассчитывается так:

5! = 5 * 4 * 3 * 2 * 1 = 120

Это, очевидно, займет меньше времени для вычисления, чем факториал 10, потому что для последнего, программа должна сделать еще пять умножений:

10! = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1

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

0 голосов
/ 02 декабря 2010

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

«постоянное время» означает «время, не зависящее от объема ввода».

0 голосов
/ 02 декабря 2010

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

...