第五章复习
引题:
(1)汉诺塔问题(非重点)
- 算法呈现:
void hanoi(int n,A,B,C){
if(n>0){
hanoi(n-1,A,C,B); //A->C,B作辅助
move(A,B); //A->B
hanoi(n-1,C,B,A); //C->B,A作辅助
}
}
(2)选择排序(非重点):
- 时间复杂度:元素比较次数为C(n),那么C(n)=n(n-1)/2;
(3)插入排序(非重点):
- 时间复杂度:O(n^2);
整数幂(重点)
目标:计算x的n次幂
计算方式:
(1):连续乘x
eg : x->x2->x3->x^4->········;
(2):平方(适用性不强):
eg : x->x2->x4->x^8->·····;
(3):算法实现思路(5.4)
如果能计算出x的b次幂,b=⌊n/2⌋;
那么就可以计算出x的n次幂
例:t = x^b;
如果n为偶数,y=t^2;
反之,y = x*t^2;
算法呈现:
power(x,m){
if(m=0){
y=1;
}
else{
y=power(x,⌊n/2⌋);
y=y^2;
if(m为奇数){
y= x*y;
}
}
return y;
}
算法分析:时间复杂度O(㏒n);
(4):循环迭代的实现方法
前提:
任意整数n,都可以拆为若干个2的整数次幂之和,比如9=23+20,13=23+22+2^0;
- 方法一
算法思路:
x^n = x^d
k
* 2^i · x^dk-1
* 2^(i-1) · ··· · x^d0
* 2^0;如果d
i
=0,那么x^(di
*2 i)=1;如果d
i
=1,那么x^(di
*2 i)= ((x2)2 ···)^2 i次;
算法呈现:
y = 1;
for(i=k;i>=0;i--){
y = y * y;
if(d(i)==1){
y = y * x;
}
}
算法分析:时间复杂度O(㏒n);
- 方法二
算法思路:
x^n = x^d
k
* 2^i · x^dk-1
* 2^(i-1) · ··· · x^d0
* 2^0;如果d
i
=0,那么x^(di
*2 i)=1;如果d
i
=1,那么x^(di
*2 i)=(x^(2 * i-1))^2;
算法实现:
y = 1;
t = n;
p = x;
while(t>0){
if (t mod 2){
y= y * p;
}
t =t / 2;
p = p * p;
}
算法分析:时间复杂度O(㏒n);空间复杂度O(1);
多项式求值
-
引题&方法一:
P
n
(x) = an
* xn+ an-1
* x(n-1)+ … +a1
* x+a0
;对于任意i,那么a
i
* xi = ai
* x * x * x * x * … * x; i次算法呈现:
y = a[n]; for(j=1;j<=n;j++){ p = x * p + a[n-1]; } return p;
-
方法二:
P
n
(x) = an
* x^n+ an-1
* x^(n-1)+ … +a1
* x+a0
;算法呈现:
y=a[0]; p =1; for (i =1 ;i<=n;i++){ p = p * x; y = y + a[i] * p; } return y;
算法分析:时间复杂度O(n),空间复杂度O(1);
寻找多数元素(非重点)
-
多数元素定义:出现次数大余n/2的元素;
-
直观的方法:
- 蛮力法(比较)
- 先排序再判断
-
结论5.1
在原序列中去除两个不同的元素后,那么在原序列中的多数元素在新序列中还是多数元素。
-
实现过程
-
找出可能是多数元素的值
-
算法思路:
找出A[m,…,n]可能是多数元素的值(候选者);
count初始值设为1;如果A[j]=A[m],则count++;否则count–;
当count减到0时,说明了删掉若干两两不对等的元素对;
后续使用递归调用即可;
-
算法呈现:
void candidate(m){ j = m; c = A[m]; count = 1; while(j<n&&count>0){ j = j+1; if(A[j]==c){ count ++; } else { count -- ; } } if(j=n) return c; else return candidate(j+1); }
- 算法分析:时间复杂度O(n);
-
-
判断这个可能值是否是多数元素
- 算法呈现:
count = 0; for (j=1;j<=n;j++){ if(A[j]=c){ count = count + 1; } } if(count>⌊n/2⌋){ return c; } return none;
- 算法分析:时间复杂度O(n);
-
算法分析:时间复杂度O(n);
-
第六章复习
引言
- 问题:找出A[1,…,n]的最大值和最小值;
- 直观的方法:
x = A[1];
y = A[1];
for(i=2;i<=n;i++){
if(A[i]<x){
x = A[i];
}
if(A[i]>y){
y = A[i];
}
}
return(x,y);
比较次数:2n-2;
- 分治法(假设n是2的整数幂):
mid = ⌊(low+high)/2⌋;
(x1,y1) = minmax(low,mid);
(x2,y2) = minmax(mid+1,high);
x = min{
x1,x2};
y = max{
y1,y2};
比较次数:C(n)= 1 (n=2) 或者C(n) = 2*C(n/2) +2 (n>2);
-
分治法的复杂分析(元素比较次数)
C(n) = 2 * C(n/2) + 2 = 2 * (2 * C(n/4) + 2) + 2 = 4 * C(n/4) + 4 + 2 = 4 * (2 * C(n/8) + 2) + 4 + 2 = 8 * C(n/8) + 8 + 4 +2
···
= 2(k-1) * C(2) + ∑ j = 1 k − 1 2 j \sum_{j=1}^{k-1}2^j ∑j=1k−12j = 3 * (n/2) - 2;
二分搜索(分治思路)
- 算法呈现:
void binarysearch(low,high){
if(low>high){
return 0;
}
else {
mid = ⌊(low+high)/2⌋;
if(x = A[mid]){
return mid;
}
else{
if(x<A[mid]){
return binarysearch(low,mid-1);
}
return binarysearch(mid+1,high);
}
}
}
- 算法分析:
- 复杂度(最坏情况下):令n = high - low + 1,C(n)表示最坏情况下的比较次数
- 那么 C ( n ) = { 1 ( n = 1 ) 1 + C ( ⌊ n / 2 ⌋ ) ( n ≥ 2 ) C(n) = \begin{cases} 1 (n=1)\\ \ 1+C(⌊n/2⌋) (n\geq2) \end{cases} C(n)={ 1(n=1) 1+C(⌊n/2⌋)(n≥2)
- 不妨设2k-1 ≤ \leq ≤n<2k ,则C(n) ≤ \leq ≤ 1+C(⌊n/2⌋) ≤ \leq ≤ 1+C(⌊n/4⌋) ··· ≤ \leq ≤ (k-1) + C(⌊n/2k-1⌋) = k
- 所以,C(n)=O( log \log logn);
合并排序(分治思路)
- 算法呈现:
mergesort(low,high){
if