一,算法
算法:解决特定问题求解步骤的描述。在计算机中表现为指令的有限序 列,每条指令可表示一条个或多个操作。
二,算法具有五个特性
- 输入:算法具有零个或多个输入。
- 输出:只有一个或多个输出。
- 有穷性:算法在执行有限的步骤之后,自动结束而不会出现无限循环,并且一个步骤在可接受的时间内完成。就是不会出现死循环。。。
- 确定性:每一个步骤都有确定含义,不会出现二义性
- 可行性:每一步都能够通过执行有限次数完成 。
总结一下就三点:正确;能完结;无二义性。
三,度量一个算法的好与坏——–时间复杂度和空间复杂度
算法的时间复杂度和空间复杂度统称为算法的复杂度。
- 时间复杂度:
(1)时间频度:一个算法中语句执行次数,记为T(n)。
时间复杂度实际上就是一个函数,该函数计算的是执行基本操作的次数。一个算法语句的执行次数是关于问题规模n的某个函数,我们把它记为f(n),n就是问题的规模。当问题规模N变化时,T(n)也在变化,算法执行次数的增长速率和f(n)的增长速率相同,即T(n)=f(n)。当n趋于无穷大时,T(n)/f(n)的极限值为不等于零的常数,则成f(n)是T(n)的同数量级函数,记作T(n)=O(f(n)),称O(f(n))为时间复杂度的O渐进表示法,也就是时间复杂度。
(2)最好,最坏和平均算法复杂度:
最好情况下:任意输入规模下的最大运行次数(上界)。
最坏情况下:任意输入规模下的最小运行次数(下界)。
平均情况:任意输入规模下的期望运行次数。
我们一般讨论的都是最坏情况下的时间复杂度,因为
1)最坏情况下的时间复杂度是任何输入下的运行时间上界。
2) 对于某些算法,最坏情况出现的较为频繁。
(3) 求时间复杂度
一般算法O(n)计算方法:
*用常数1取代运行时间中的所以加法常数
*在修改后的运行次数函数中,只保留最高阶
*如果最高阶系数存在且不是1,则去除与这个项相乘的常数
例如:
int count = 0;//1
for (int i = 0; i < 10; i++)//10
{
count++;//10
}
这段程序的执行次数f(n)=1+10+10=21,用1取代加法常数,将基本语句执行次数的数量级放入O(f(n))中即O(1);
再例如:
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
x++;
}
for (i = 0; i < n; i++)
x++;
第一个for循环的时间复杂度是O(n^2);第二个for循环的时间复杂度是O(n);第三个for循环的时间复杂度是O(n);,整个算法的时间复杂度是O(n^2+n) 保留最高阶即为O(n^2);
在计算时间复杂度有几个分析法则:
第一:简单的输入输出语句或赋值语句,近似认为是O(1);
第二:对于顺序结构,用求和法则;
第三:对于选择结构,如if语句,它耗费的时间是在执行then 或else时所用时间,检验条件也要用时O(1);
第四:对于循环结构,用乘法法则。
与刚才的计算方法本质其实是一样的。
举个例子:
1.int i = 1;//1
2.while (i <= n)
3.{
4. i = i * 2;
5.}
第一行是O(1),第4行的频度是f(n),2^f(n)<=n; f(n)<=log2n,即T(n)=O(log2n);
常见的时间复杂度:
常用的时间复杂度所耗费的时间从小到大依次是:
O(logn),O(n),O(nlogn),O(n^2),O(n^3)成为多项式时间,而O(2^n),O(n^3)成为指数时间。前者为有效算法,这类问题成为P类(多项式)问题,后者成为NP(非确定多项式)问题。
2.空间复杂度
一个算法的空间复杂度是该算法所耗费的存储空间,它是问题规模n的函数,一般情况下用O的渐进表示法,渐进空间复杂度也简称为空间复杂度。
空间复杂度在计算时要考虑到函数调用所需要的空间,以及动态开辟的空间,递归栈所需的空间。