文章目录
在讲题目中的概念的时候,先介绍涉及到的基本概念。
时间复杂度
多项式polynomial:类似于 a x n − b x n − 1 + c ax^n-bx^{n-1}+c axn−bxn−1+c这样的式子。
对于规模为n的输入,它们在最坏的情况下的运行时间为O( n k n^k nk),其中k为某个常数,则该算法为多项式时间的算法。
在计算复杂度的理论中,算法的计算时间也就是时间复杂度m(n)不大于算法规模n的多项式倍数,即m(n)是关于n的一个多项式函数。例如,时间复杂度为O( n 2 n^2 n2)就是多项式时间,而时间复杂度为O( 2 n 2^n 2n)的则不是关于n的多项式函数,因此就不是多项式时间。
关于多项式时间参见:能否用通俗的语言解释『多项式时间』?
计算机算法求解问题中常用空间复杂度和时间复杂度表示算法的运行效率。
空间复杂度:一个算法在计算过程中要占用的内存空间的大小。
时间复杂度:算法运行得到想要的解所需要的计算工作量。其探讨的是当输入值接近无穷∞时,算法所需工作量的变化的快慢程度。其表示当问题规模扩大后,程序需要的时间长度增长得有多快;并不是表示一个程序解决问题需要花多少时间。
也就是说,对于高速处理数据的计算机来说,处理某个特定数据的效率不能衡量一个程序的好坏,而应该看当这个数据的规模变大到数百倍后,程序运行时间是否还是一样,或者也跟着慢了数百倍,或者变慢了数万倍。
不管数据有多大,程序处理花的时间始终是那么多的,就说这个程序很好,具有O(1)的时间复杂度,也称常数级复杂度;
数据规模变得有多大,花的时间也跟着变得有多长,比如找n个数中的最大值,这个程序的时间复杂度就是O(n),为线性级复杂度;
而像冒泡排序、插入排序等,数据扩大2倍,时间变慢4倍的,属于O( n 2 n^2 n2)的复杂度,为平方级复杂度。
还有一些穷举类的算法,所需时间长度成几何阶数上涨,这就是O( a n a^n an)的指数级复杂度,
甚至O(n!)的阶乘级复杂度。
不会存在O( 2 n 2 2n^2 2n2)的复杂度,因为前面那个系数“2”根本不会影响到整个程序的时间增长。同样地,O( n 3 + n 2 n^3+n^2 n3+n2)的复杂度也就是O( n 3 n^3 n3)的复杂度。
因此,可以说,一个O( 0.01 n 3 0.01n^3 0.01n3)的程序的效率比O( 100 n 2 100n^2 100n2)的效率低,尽管在n很小的时候,前者优于后者,但后者时间随数据规模增长得慢,最终O( n 3 n^3 n3)的复杂度将远远超过O( n 2 n^2 n2)。我们也说,O( n 100 n^{100} n100)的复杂度小于O( 1.0 1 n 1.01^n 1.01n)的复杂度。
前面的说明中的几类复杂度可分为两种级别:多项式级别的时间复杂度和非多项式级别的时间复杂度。后者的复杂度无论如何都远远大于前者。
-
多项式级别的时间复杂度:常数级O(1)、 l o g n log_n logn级别、 n a n^a na级别。特点规模n出现在底数的位置
-
非多项式级别的时间复杂度: a n a^n an级别、 n ! n! n!级别。其复杂度计算机往往不能承受。
解决一个问题时选择的算法通常都需要是多项式级的复杂度,非多项式级的复杂度需要的时间太多,往往会超时,除非数据规模非常小。
但是,并非所有的问题都能找到复杂度为多项式级别的算法。有些问题甚至根本不可能找到一个正确的算法来,这称之为“不可解问题”(Undecidable Decision Problem)。The Halting Problem就是一个著名的不可解问题。
再比如,输出从1到n这n个数的全排列。不管你用什么方法,你的复杂度都是阶乘级,因为你总得用阶乘级的时间打印出结果来。有人说,这样的“问题”不是一个“正规”的问题,正规的问题是让程序解决一个问题,输出一个“YES”或“NO”(这被称为判定性问题),或者一个什么什么的最优值(这被称为最优化问题)。那么,根据这个定义,我也能举出一个不大可能会有多项式级算法的问题来:Hamilton回路。问题是这样的:给你一个图,问你能否找到一条经过每个顶点一次且恰好一次(不遗漏也不重复)最后又走回来的路(满足这个条件的路径叫做Hamilton回路)。这个问题现在还没有找到多项式级的算法。事实上,这个问题就是我们后面要说的NPC问题。
确定性算法与非确定性算法
确定性Determinism算法:
设A是求解问题B的一个解决算法,在算法的整个执行过程中,每一步都能得到一个确定的解,这样的算法就是确定性算法。
非确定性Nondeterminism算法:
设A是求解问题B的一个解决算法,它将问题分解成两部分,分别为猜测阶段和验证阶段,其中
- 猜测阶段:此阶段,对问题的一个特定的输入实例x产生一个任意字符串y,在算法的每一次运行时,y的值可能不同,因此,猜测以一种非确定的形式工作。
- 验证阶段:此阶段,用一个确定性算法(有限时间内)验证。①检查在猜测阶段产生的y是否是合适的形式,如果不是,则算法停下来并得到no;② 如果y是合适的形式,则验证它是否是问题的解,如果是,则算法停下来并得到yes,否则算法停下来并得到no。它是验证所猜测的解的正确性。
P类问题(Polynomial)-NP问题的子集
P类问题:若一个问题可以找到一个能在多项式的时间里解决它的算法,即能在多项式时间内可解的问题;是**“确定性计算机”能够在“多项式时间”解决的所有问题**
常见的一些信息奥赛的题目都是P问题。道理很简单,一个用穷举换来的非多项式级时间的超时程序不会涵盖任何有价值的算法。
NP问题(Non-deterministic Polynomial)-NPC问题的子集
NP问题:可以在多项式的时间里验证/猜出一个解的问题。即不能判定这个问题到底有没有解,而是猜出一个解来在多项式时间内证明这个解是否正确。也就是说,该问题的猜测过程是不确定的,而对其某一个解的验证则能够在多项式时间内完成。P类问题属于NP问题,但NP类问题不一定属于P类问题。
P 类问题: “确定性计算机”能够在“多项式时间”解决的所有问题
NP 问题: “非确定性计算机”能够在“多项式时间”解决的所有问题 由此可知,P≠NP
著名的NP类问题:旅行家推销问题(TSP)。即有一个推销员,要到n个城市推销商品,他要找出一个包含所有n个城市的环路,这个环路路径小于a。我们知道这个问题如果单纯的用枚举法来列举的话会有(n-1)! 种,已经不是多项式时间的算法了(注:阶乘算法比多项式的复杂)。那怎么办呢?我们可以用猜的,假设我人品好,猜几次就猜中了一条小于长度a的路径,我画画画画,好的,我得到了一条路径小于a的环路,问题解决了,皆大欢喜。可是,我不可能每次都猜的那么准,也许我要猜完所有种呢?所以我们说,这是一个NP类问题。也就是,我们能在多项式的时间内验证并得出问题的正确解,可是我们却不知道该问题是否存在一个多项式时间的算法,每次都能解决他(注意,这里是不知道,不是不存在)。
NPC问题
NPC问题:存在这样一个NP问题,所有的NP问题都可以约化成它。换句话说,只要解决了这个问题,那么所有的NP问题都解决了。
其定义要满足2个条件:①它是一个NP问题;②所有NP问题都能规约到它。
证明npc问题的思路是:①先证明它至少是一个NP问题,②再证明其中一个已知的NPC问题能约化到它。
规约/约化Reducibility(介绍NPC问题引入的概念)
问题A可规约为问题B:问题A可以约化为问题B,即问题B的解一定是问题A的解,因此解决A不会难于解决B。由此可知问题B的时间复杂度一定大于等于问题A。**《算法导论》**中有一个例子——现在有两个问题:求解一个一元一次方程和求解一个一元二次方程。那么可以说,前者可规约为后者,意思是知道如何解一个一元二次方程那么一定能解出一元一次方程。我们可写出两个程序分别对应两个问题,那么我们能找到一个“规则”,按照这个规则把解一元一次方程程序的输入数据变一下,用在解一元二次方程的程序上,两个程序总能得到一样的结果。这个规则即是:两个方程的对应项系数不变,一元二次方程的二次项系数为0。
按照这个规则把前一个问题转换成后一个问题,两个问题就等价了。
同样地,我们可以说,Hamilton回路可约化为TSP问题(Travelling Salesman Problem,旅行商问题):在Hamilton回路问题中,两点相连即这两点距离为0,两点不直接相连则令其距离为1,于是问题转化为在TSP问题中,是否存在一条长为0的路径。Hamilton回路存在当且仅当TSP问题中存在长为0的回路。
“问题A可约化为问题B”有一个重要的直观意义:B的时间复杂度高于或者等于A的时间复杂度,即问题A不比问题B难。这很容易理解。既然问题A能用问题B来解决,倘若B的时间复杂度比A的时间复杂度还低了,那A的算法就可以改进为B的算法,两者的时间复杂度还是相同。正如解一元二次方程比解一元一次方程难,因为解决前者的方法可以用来解决后者。
约化具有一项重要的性质:约化具有传递性。如果问题A可约化为问题B,问题B可约化为问题C,则问题A一定可约化为问题C。
约化的标准概念:若能找到这样一变化法则,对任意一程序A的输入,都能按此法则变换成程序B的输入,使两程序的输出相同,则称问题A可约化为问题B
当然,我们所说的“可约化”是指的可“多项式地”约化(Polynomial-time Reducible),即变换输入的方法是能在多项式的时间里完成的。约化的过程只有用多项式的时间完成才有意义。
从规约的定义中我们看到,一个问题规约为另一个问题,时间复杂度增加了,问题的应用范围也增大了。通过对某些问题的不断规约,我们能不断寻找复杂度更高,但应用范围更广的算法来代替复杂度虽然低,但只能用于很小的一类问题的算法。
存在这样一个NP问题,所有的NP问题都可以约化成它。换句话说,只要解决了这个问题,那么所有的NP问题都解决了。这种问题的存在难以置信,并且更加不可思议的是,这种问题不只一个,它有很多个,它是一类问题。这一类问题就是传说中的NPC问题,即NP-完全问题。
NP难问题
NP-Hard问题:满足NPC问题定义的第二条但不一定要满足第一条(即NP-Hard问题要比 NPC问题的范围广,NP-Hard问题没有限定属于NP问题),即所有的NP问题都能约化到它,但是它不一定是一个NP问题。
NP-Hard问题同样难以找到多项式的算法,但它不列入我们的研究范围,因为它不一定是NP问题。即使NPC问题发现了多项式级的算法,NP-Hard问题有可能仍然无法得到多项式级的算法。事实上,由于NP-Hard放宽了限定条件,它将有可能比所有的NPC问题的时间复杂度更高从而更难以解决。
机器学习中的过拟合与N/NP问题
机器学习面临的问题通常是NP-hard甚至更难,而有效的学习算法必然是在多项式时间内运行完成,若可彻底避免过拟合,则通过经验误差最小化就能获最优解,这就意味着我们构造性地证明了“P=NP”,因此,只要相信“P≠NP”,过拟合就不可避免。【摘自周志华《机器学习》】
参考链接:什么是P问题、NP问题和NPC问题