先上一张图,后面慢慢写:
要弄清楚P、NP、NPC和NP-Hard问题,需要先了解一下时间复杂度;然后再考察我们所关注问题是不是可解。
1 时间复杂度
1.1 什么是时间复杂度
时间复杂度又叫做时间复杂性,用以从时间维度上定性描述算法运行消耗的时间。
算法的运行时间受多种因素影响。
其一:计算机本身性能的不同在很大程度上影响着算法运行所需的时间。抛开计算机性能的影响,可知算法花费的时间与算法中语句的执行次数成正比。因此,可以用算法中语句的执行次数(频度)对算法运行时间进行定量的分析。
其二:不同规模的输入值会导致算法运行所需时间不同。当问题规模扩大时,算法运行时间的增长速度是完全不同的。比如:在长度为n的数组中查找最小值,当n增大时,所需的随着n的增长而线性增长;但在冒泡排序中,数组长度增加2倍,所需时间将增加4倍。
其三:相同规模但数据不同的输入值也会影响算法的运行时间。对于此种情况,我们通常采用算法运行的最坏情况来计算时间复杂度,即任意大小的输入n所需的最大运行时间。
因此,我们通常按照问题规模来定义时间复杂度,而不是考量算法真实的运行时间,即只关注算法运行时间随问题规模增长的变化趋势。
时间复杂度通常用大O符号表示,记作:T(n) = O(f(n))(算法的渐进时间复杂度),其中*f(n)*表示每行代码执行的次数之和,O表示正比例关系。
1.2 常见时间复杂度
常见的时间复杂度有:
常数阶O(1)
对数阶O(logN)
线性阶O(n)
线性对数阶O(nlogN)
平方阶O(n²)
立方阶O(n³)
K次方阶O(n^k)
指数阶(2^n)
可以看出:这些时间复杂度从上到下越来越大,执行效率越来越低。
1.3 时间复杂度级别
时间复杂度可分成两种级别:一种是多项式级别复杂度,其特征是规模n出现在底数的位置,例如:常数阶O(1)、对数阶O(logN)、线性阶O(n)、平方阶O(n²)、立方阶O(n³)、K次方阶O(nk)等;一种是**非多项式级别复杂度**,比如:指数阶O(2n),阶乘阶O(n!),此类情况往往是计算机不可承受的。
注意:我们在解决一个问题时,通常要选择多项式级别复杂度的算法。除非问题规模较小,尽量不采用非多项式级别复杂度的算法。