第二章:递归与分治
1, 请问二分搜索算法、快速排序算法、线性时间选择算法和最近点对问题的时间复杂性各为多少?
答:二分搜索算法:最坏情况O(logn)、
快速排序算法:最坏情况O(n2),最好情况和平均情况均为O(nlogn)
线性时间选择算法:最坏情况O(n)
最近点对问题:时间复杂性O(nlogn)
2, 分治法的基本思想是什么?分治法的要领是什么?(分治法可分为哪三个主要步骤?)
答:分治法的基本思想:是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题互相独立且与原问题相同。递归地解这些子问题,然后将各子问题的解合并得到原问题的解。
分治法是把一个规模较大的问题分解为若干个规模较小的子问题,这些子问题相互独立且与原问题同类; 首先求出这些子问题的解,然后把这些子问题的解组合起来得到原问题的解。由于子问题与原问题是同类的,故使用分治法很自然地要用到递归。
因此分治法分三步:
1 ),将原问题分解为子问题(Divide)
2 ),求解子问题(Conquer)
3 ),组合子问题的解得到原问题的解(Combine)
3,分治法的适用条件是什么?
答:分治法所能解决的问题一般具有以下几个特征:
该问题的规模缩小到一定的程度就可以容易地解决;
该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质
利用该问题分解出的子问题的解可以合并为该问题的解;
该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子问题。
4,二分搜索算法程序:
答
public static int find(int[] data,int goal,int left,int right){ int mid = (left+right)/2 ; if(left>right){ return -1 ; } if(goal==data[mid]){ return mid ; } else if(goal<data[mid]){ //注意right = mid -1 ; return find(data,goal,left,mid-1); } else if(goal>data[mid]){ return find(data,goal,mid+1,right); } return -1 ; //未找到 }
| template<class Type> int BinarySearch(Type a[], const Type& x, int L, int R){ while (R >= L){ int m = (L+R)/2; if (x == a[m]) return m; if (x < a[m]) R = m-1; else L = m+1; } return -1; }
|
例题:
1,排列问题:
设计一个递归算法生成n个元素{r1,r2,…,rn}的全排列。
解:
Template<class type>
void Perm(Type list[ ], int k, int m)
{//Generate all permutations of list[k:m].
if (k==m) //第一版中有错误
{//list[k:m] has one permutation, output it
for (int i=0;i<=m;i++)
cout<<list[i];
cout<<endl;
}
else//list[k:m] has more than one permutation
//generate these recursively
for(i=k;i<=m;i++)
{ Swap(list[k],list[i]);
Perm(list,k+1,m);
Swap(list[k],list[i]);
}