java算法:分治法

java算法:分治法

分治法用于算法设计的最重要实例:在一个程序中使用两个或多个递归调用。

例1:用分治法找到最大值

Java代码 复制代码
  1. staticdoublemax(doublea[],intl,intr){
  2. if(l==r){
  3. returna[l];
  4. }
  5. intm=(l+r)/2;
  6. doubleu=max(a,l,m);
  7. doublev=max(a,m+1,r);
  8. if(u>u){
  9. returnu;
  10. }else{
  11. returnv:
  12. }
  13. }
static double max(double a[], int l, int r){
	if(l == r){
		return a[l];
	}
	int m = (l + r)/2;
	double u = max(a, l , m);
	double v = max(a, m + 1, r);
	if(u > u){
		return u;
	}else{
		return v:
	}
}

分治法比简单的循环算法更加快捷。

一个有趣的例子:3个柱子和N个与柱子配套的盘子,盘子大小不同,从N(大)到1(小)的顺序放在其中一个柱子上。任务:移动到最右边的柱子上。一次只能移动一个,大的盘子不能放在小的盘子上。

例2:汉诺塔问题的递归分治法所产生的解决方法要移动2的N次方-1次。

Java代码 复制代码
  1. staticvoidhannoi(intn,intd){
  2. if(n==0){
  3. return;
  4. }
  5. hanoi(n-1,-d);
  6. shift(n,d);
  7. hanoi(n-1,-d);
  8. }
static void hannoi(int n, int d){
	if(n == 0){
		return;
	}
	hanoi(n - 1, -d);
	shift(n, d);
	hanoi(n - 1, -d);
}

例3:用分治法画刻尺

Java代码 复制代码
  1. staticvoidrule(intl,intr,inth){
  2. intm=(l+r)/2;
  3. if(h>0){
  4. rule(l,m,h-1);
  5. mark(m,h);
  6. rule(m,r,h-1);
  7. }
  8. }
static void rule(int l, int r, int h){
	int m = (l + r)/2;
	if(h > 0){
		rule(l, m, h - 1);
		mark(m, h);
		rule(m, r, h - 1);
	}
}

对于任意给定的i,有更简单的方法来计算第i个标记长度:即i的二进制尾数0的个数。

Java代码 复制代码
  1. 00001
  2. 000101
  3. 00011
  4. 001002
  5. 00101
  6. 001101
  7. 00111
  8. 010003
  9. 01001
  10. 010101
  11. 01011
  12. 011002
  13. 01101
  14. 011101
  15. 01111
  16. 100004
  17. 10001
  18. 100101
  19. ...
0 0 0 0 1
0 0 0 1 0  1
0 0 0 1 1
0 0 1 0 0  2
0 0 1 0 1 
0 0 1 1 0  1
0 0 1 1 1 
0 1 0 0 0  3
0 1 0 0 1
0 1 0 1 0  1
0 1 0 1 1  
0 1 1 0 0  2
0 1 1 0 1 
0 1 1 1 0  1
0 1 1 1 1
1 0 0 0 0  4
1 0 0 0 1
1 0 0 1 0  1
...

例4:画刻尺的非递归程序

Java代码 复制代码
  1. staticvoidrule(intl,intr,inth){
  2. for(intt=1,j=1;t<=h;j+=j,t++){
  3. for(inti=0;l+j+i<=r;i+=j+j){
  4. mark(l+j+i,t);
  5. }
  6. }
  7. }
static void rule(int l, int r, int h){
	for(int t = 1, j = 1; t <= h; j += j, t++){
		for(int i = 0; l +j + i <= r; i += j + j){
			mark(l + j + i, t);
		}
	}
} 

一般来说,许多递归程序取决于解决子问题的特定顺序,但对于另一些算法(用分治法找最大值),则与解决子问题的顺序无关。对于这样的算法,唯一的限制条件是我们再解决主问题之前必须先解决子问题。什么时候可以重排计算是很重要的。在考虑并行处理器上实现算法时,这个问题就更重要了。自底向上的方法与一般算法设计的思路是一样的,即总先解决那些容易处理的子问题,然后把这些解结合起来,从而解决稍大的子问题,直到整个问题得于解决,这种方法就是分治法。

快速排序和折半查找是基本的分治法思想的变体,即把问题分成大小为k-1和N-k的子问题,k值由输入决定。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值