c2java select algorithm

对于很多应用来说,随机算法是最简单的或者最快的。既简单又快的有没有呢?
那需要深刻的洞察力或者革命性的突破。


什么是随机算法
随机算法与确定算法区别是:它还接收输入随机比特流来做随机决策。
对于同一个输入,每次运行所用的算法行为都不同,虽然结果都是一样的。


Foiling an adversary
可以构造一个输入使得一个确定性算法运行时间最长。
随机算法可以看作是从一族算法中随机选出来的一个算法。




快速排序O(NlgN)的精髓在于随机化划分。
快速的意思是常数因子是1.38。
标准库里面采用小规模插入排序,非递归化,三分能进一步提高20%的速度。
理想情况是均分两个子问题。如果每次都分为9:1, 
T(n) = T(9n/10) + T(n/10) + cn,
则递归树高度是log_{10/9} n = ? lgn。


如果输入是已经排好顺序的,则随机化
则打破这种顺序。有没有可能反而随机成一个升序或者降序呢?
概率是1/N!, 这么小的概率我们认为不可能发生的(当然,严格实时系统除外)。
因此我们高概率的认为运行时间是期望的。


线性时间的选择算法用在动态/在线输入情景时才有意义。
如果是静态输入,我们可以对整个输入做随机排列。
动态输入因为在某一个时刻只看到部分,就不能这样干了。


划分
int randomPartition(int[] a, int p, int r) 实现上是很精妙的。
是维持这个不变量:[p..i] <= x < [i+1, j)
我也是原样抄过来,对最先写出这段代码的程序员致敬。

public class Random
{
	static int random(int a, int b)
	{
		return a + (int)Math.round(Math.random() * (b-a));
	}

	static void swap(int[] a, int i, int j)
	{
		int t = a[i]; a[i] = a[j]; a[j] = t;
	}

	static int randomPartition(int[] a, int p, int r)
	{
		int x, i, j;
		i = random(p, r);
		swap(a, r, i);
		
		x = a[r];
		i = p - 1;
		for(j = p; j < r; ++j)if(a[j] <= x){
			++i;
			swap(a, i, j);
		}	
		swap(a, i+1, r);
		return i+1;
	}

	static int randomSelect(int[] a, int p, int r, int i)
	{
		int q, k;
		if(p == r)return a[p];
		q = randomPartition(a, p, r);
		k = q - p + 1;
		if(i == k)return a[q];
		else if(i < k)return randomSelect(a, p, q-1, i);
		else return randomSelect(a, q+1, r, i-k);
	}

	public static void main(String[] arg)
	{
		int[] a = {3,2,9,0,7,5,4,8,6,1};
		for(int i = 0; i < a.length; ++i){
			int t = randomSelect(a, 0, a.length-1, i+1);
			System.out.printf(" %d", t);
		}
		System.out.printf("%n");
	}
}

[] http://www.ece.northwestern.edu/~nickle/randAlg/Karp91.pdf


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值