算法导论断断续续看了一小部分,但是还没有写过总结和笔记,很多思考和学习到的东西都随着时间流失掉了(痛心)。
下面进入正题:
1.最大值和最小值问题
最简单的确定一个有n个元素的集合中最小元素(最大元素)的方法就是所谓“打擂台”的思路。遍历集合,过程中将每个元素与现在所持有的最小元素进行比较,如果该元素小于现有最小元素则更新最小元素为该元素,否则继续遍历。可见至少要进行n-1次比较,从次数看来,这个算法是最优的。
那么,如果要同时找出最小元素和最大元素的话,该怎么做?
(1).若n为奇数,则max=arr[0],min=arr[0];
若n为偶数,则max=arr[0],min=arr[1];
(2).集合中每两个元素组成一对,分别求其大小关系。
(3).遍历集合,将max和min与每对元素集中的最大元素与最小元素比较,进行更新
分奇数和偶数的情况是因为奇数个元素的集合不能被正好分成n/2个集合,所以干脆将第一个元素孤立出来。
现在分析比较次数:
奇数:遍历n/2个子集,max和min分别比较,加上每个子集内部比较,于是总共是3*floor(n/2)次.
偶数:第一次max和min子集的初始化比较,加上(n-2)/2个子集内部比较,加上遍历的2*(n-2)/2次比较,所以总共是3n/2-2次比较。
2.选择算法(期望为线性时间)
这里提供了一个分治算法来确定集合中的第i个元素。
(1).p为集合第一个元素,r为元素最后一个元素,q为分区关键字索引,i为所求元素在集合中的次序
(2).对集合中的元素进行一次基于快速排序的随机分区(randomized-patition),并得到分区关键元素的索引值q。
(3).k=q-p+1,得到q之后的分区首元素,此时k代表q在该集合中的索引,而q得到的是整个集合中的索引值.
(4).若k=i,则返回A「q」,
若k>i,返回调用select(A,p,q-1,i)
若k<i,返回调用select(A,q+1,r,i-k)
下面贴上java实现:
import java.util.Random;
public class RandomSelect {
public static void exchange(int[] arr,int i,int j) {
if(i<0||i>=arr.length||j<0||j>=arr.length||i==j)
return;
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
public static int patition(int[] arr,int p,int r) {
Random random=new Random();
int index=Math.abs(random.nextInt(r));
while(index<p)
index=Math.abs(random.nextInt(r));
exchange(arr,r,index);
int x=arr[r];
int i=p-1;
for(int j=p;j<r;j++) {
if(arr[j]<x) {
i++;
exchange(arr,i,j);
}
}
exchange(arr,i+1,r);
return i+1;
}
public static int randomized_select(int[] arr,int p,int r,int i) {
if(p==r)
return arr[p];
int q=patition(arr,p,r);
int k=q-p+1;
if(k==i)
return arr[q];
if(i<k)
return randomized_select(arr,p,q-1,i);
else
return randomized_select(arr,q+1,r,i-k);
}
public static void main(String...args) {
int[] arr={2,5,4,6,35,11,7,55,3,73,80};
System.out.println(randomized_select(arr,0,arr.length-1,arr.length));
}
}
了解了基本的算法,下面对时间期望进行分析:
k-1和n-k分区是随机分区分出的两个子集,对T(n)求期望值
E(T(n))<=E(∑nk=1·T(max(k−1,n−k)))+O(n)=∑1/n·E(T(max(k−1,n−k)))+O(n)
所以,
E[T]<=2/n·∑k=n/2n−1E[T(n)]
接下来将On(n)替换为an,并做一个假设:
E[T(n)]<=cn
:
E[T]<=2/n·∑k=n/2n−1ck+an=cn−((cn/4)−c/2−an)
(1) 具体的化简请看《算法导论》p122页的演绎
最终,
(cn/4)−c/2−an>=0
就可以证明(1)式至多为cn,得到结果
n>=2c/(c−4a)
如果假设对
n<2c/(c−4a)
,只要
T(n)=O(1)
那么
E(T(n))=O(n)
,期望为线性。因此,若集合元素互异,可以做到在线性时间内找到任一顺序统计量