第二章 算法分析

来源:互联网 发布:淘宝达人和微淘 编辑:程序博客网 时间:2024/05/16 23:53

·如何估计一个程序所需要的时间。

·如何将一个程序的运行时间从天或年降低到秒。

·错信地使用递归的后果。

·将一个数自乘得到其幂以及计算两个数的最大公因数的非常有效的算法。


摘要:

1、运行时间的计算。N的增长要快于logN的任意次幂。计算时间复杂度的基本策略是从内部(最深层部分)向外展开。

2、当递归被正常使用时,将其转换成一个简单的循环结构是相当困难的。

3、分治策略。把问题分成两个大致相等的子问题,然后递归地对它们求解,这是“分”部分。“治”阶段将两个子问题的解合并到一起并可能再做些少量的附加工作,最后得到整个问题的解。

4、除分治算法外,可将对数出现的规律概括为一般法则:如果一个算法用常数时间O(1)将问题的大小削减为其一部分(通常是二分之一),那么该算法就是O(logN)。另一方面,如果使用常数时间只是把问题减少一个常数(如将问题减少1),那么这种算法就是O(N)的。


练习:

1、求序列的最大子序列和。若元素都为负数,何为零。

int fun(int a[ ], int n)
{
int sum, thissum, i;
sum = thissum = 0;
for(i = 0; i < n; ++i) {
thissum += a[i];
if(thissum > sum) {
sum = thissum;
}
if(thissum < 0) {
thissum = 0;
}
}
return sum;
}

2、对分查找,前提是序列已排序。时间复杂度为logN。

int fun(int a[ ], int n, int x)
{
int low, high, mid;
low = 0;
high = n - 1;
while(low <= high) {
mid = (low + high) / 2;
if(x < a[mid]) {
high = mid;
} else(x > a[mid]) {
low = mid;
} else {
return a[mid];
}
}
return -1;
}

3、计算最大公因数的欧几里德算法。假设m >= n。(如果n > m,则循环的第一次迭代将它们互相交换)

http://zh.wikipedia.org/wiki/%E6%AC%A7%E5%87%A0%E9%87%8C%E5%BE%97%E7%AE%97%E6%B3%95

算法的演示动画。最初的绿色矩形的长和宽分别是a = 1071、b = 462,从中不断铺上462×462的正方形直到剩下部分面积是462×147;然后再铺上147×147的正方形直至剩下21×147的面积;最后,铺上21×21的正方形时,绿色部分就没有了。即21是1071和462的最大公约数.

计算a = 1071和b = 462的最大公约数的过程如下:从1071中不断减去462直到小于462(可以减2次,即商q0 = 2),余数是147:

1071 = 2 × 462 + 147.

然后从462中不断减去147直到小于147(可以减3次,即q1 = 3),余数是21:

462 = 3 × 147 + 21.

再从147中不断减去21直到小于21(可以减7次,即q2 = 7),没有余数:

147 = 7 × 21 + 0.

此时,余数是0,所以1071和462的最大公约数是21

用表格表示如下:

步骤数算式商和余数01071 = 462q0 + r0q0 = 2、r0 = 1471462 = 147q1 + r1q1 = 3、r1 = 212147 = 21q2 + r2q2 = 7、r2 = 0(算法终止)

辗转相除法可用伪代码表示如下

function gcd(a, b)    while b ≠ 0       t ← b       b ← a mod b       a ← t    return a

unsigned int  Gcd(unsigned int m , unsigned int n)

{

unsigned int rem;

while(n > 0) {

rem = m % n;

m = n;

n = rem;

}

return m;

}