Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 什么是伪多项式时间?它与多项式时间有何不同?_Algorithm_Big O_Time Complexity - Fatal编程技术网

Algorithm 什么是伪多项式时间?它与多项式时间有何不同?

Algorithm 什么是伪多项式时间?它与多项式时间有何不同?,algorithm,big-o,time-complexity,Algorithm,Big O,Time Complexity,是什么?它与多项式时间有何不同?一些以伪多项式时间运行的算法具有O(nW)(用于)或O等运行时(√n) (用于);为什么不能算作多项式时间?要理解多项式时间和伪多项式时间之间的区别,我们需要从形式化“多项式时间”的含义开始 多项式时间的常见直觉是“时间O(nk)对于某些k。”例如,在时间O(n2)中运行,这是多项式时间,而暴力求解需要时间O(n·n!),这不是多项式时间 这些运行时都引用一些跟踪输入大小的变量n。例如,在选择排序中,n表示数组中的元素数,而在TSP中,n表示图形中的节点数。为了使

是什么?它与多项式时间有何不同?一些以伪多项式时间运行的算法具有O(nW)(用于)或O等运行时(√n) (用于);为什么不能算作多项式时间?

要理解多项式时间和伪多项式时间之间的区别,我们需要从形式化“多项式时间”的含义开始

多项式时间的常见直觉是“时间O(nk)对于某些k。”例如,在时间O(n2)中运行,这是多项式时间,而暴力求解需要时间O(n·n!),这不是多项式时间

这些运行时都引用一些跟踪输入大小的变量n。例如,在选择排序中,n表示数组中的元素数,而在TSP中,n表示图形中的节点数。为了使“n”在本文中的实际含义的定义标准化,时间复杂性的正式定义将问题的“大小”定义如下:

问题输入的大小是写出该输入所需的位数

例如,如果排序算法的输入是32位整数的数组,那么输入的大小将是32n,其中n是数组中的条目数。在具有n个节点和m条边的图中,输入可以指定为所有节点的列表,后跟所有边的列表,这需要Ω(n+m)位

根据该定义,多项式时间的形式定义如下:

如果某个常数k的运行时间为O(xk),则该算法在多项式时间内运行,其中x表示给定给该算法的输入位数

当使用处理图形、列表、树等的算法时,此定义或多或少与常规定义一致。例如,假设您有一个排序算法,它对32位整数数组进行排序。如果使用类似于选择排序的方法来执行此操作,那么作为数组中输入元素数量的函数,运行时将为O(n2)。但是,输入数组中的元素数n如何对应于输入的位数呢?如前所述,输入的位数将为x=32n。因此,如果我们用x而不是n来表示算法的运行时间,我们得到运行时间是O(x2),因此算法在多项式时间内运行

类似地,假设对一个图执行此操作,这需要时间O(m+n),其中m是图中的边数,n是节点数。这与给定的输入位数有什么关系?好的,如果我们假设输入被指定为一个邻接列表(所有节点和边的列表),那么正如前面提到的,输入位数将是x=Ω(m+n)。因此,运行时间将为O(x),因此算法以多项式时间运行

然而,当我们开始讨论对数字进行运算的算法时,情况就不一样了。让我们考虑测试一个数是否为素数的问题。给定一个数字n,您可以使用以下算法测试n是否为素数:

function isPrime(n):
    for i from 2 to n - 1:
        if (n mod i) = 0, return false
    return true
那么这段代码的时间复杂度是多少?好的,内部循环运行O(n)次,每次都要做一些工作来计算n mod i(作为一个非常保守的上界,这当然可以在时间O(n3)中完成)。因此,整个算法在时间O(n4)内运行,并且可能更快

2004年,三位计算机科学家发表了一篇题为“给出一个多项式时间算法来测试一个数字是否是素数”的论文。这被认为是一个里程碑式的结果。那有什么大不了的?我们不是已经有了一个多项式时间算法,也就是上面的那个吗

不幸的是,我们没有。请记住,时间复杂度的正式定义将算法的复杂度作为输入位数的函数。我们的算法在时间O(n4)内运行,但它作为输入位数的函数是什么?好吧,写出数字n需要O(logn)位。因此,如果我们将x设为写出输入n所需的位数,那么该算法的运行时间实际上是O(24x),这不是x中的多项式

这是多项式时间和伪多项式时间区别的核心。一方面,我们的算法是O(n4),它看起来像一个多项式,但另一方面,在多项式时间的形式定义下,它不是多项式时间

要直观地了解该算法为何不是多项式时间算法,请考虑以下内容。假设我想让算法做很多工作。如果我这样写一个输入:

10001010101011

然后需要一些最坏情况下的时间,比如说
T
,才能完成。如果我现在在数字的末尾添加一位,如下所示:

100010101010111

运行时间现在(在最坏的情况下)为2T。只需再增加一位,我就可以使算法的工作量加倍

如果运行时是输入数值中的某个多项式,而不是表示它所需的位数,则算法在伪多项式时间内运行。我们的主要测试算法是伪多项式时间算法,因为它在时间O(n4)内运行,但它不是多项式时间算法,因为作为写入输入所需的位数x的函数,运行时间是O(24x)。“PRIMES in P”这篇论文之所以如此重要,是因为它的运行时间(大致)是O(log12n),作为位数的函数,它是O(x12)

那么,这有什么关系呢?我们有很多伪多项式时间的整数分解算法。然而,从技术上讲,这些算法是指数时间算法。这对于密码学非常有用:如果您想使用RSA加密,您需要能够相信我们无法轻松地计算数字。通过增加数量
// Input:
// Values (stored in array v) 
// Weights (stored in array w)
// Number of distinct items (n) //
Knapsack capacity (W) 
for w from 0 to W 
    do   m[0, w] := 0 
end for  
for i from 1 to n do  
        for j from 0 to W do
               if j >= w[i] then 
                      m[i, j] := max(m[i-1, j], m[i-1, j-w[i]] + v[i]) 
              else 
                      m[i, j] := m[i-1, j]
              end if
       end for 
end for
i.e. size of input= s =log(W) (log= log base 2)
-> 2^(s)=2^(log(W))
-> 2^(s)=W  (because  2^(log(x)) = x)