基本算法之分治算法
一.分治算法的基本思想
分治算法的基本思想是将一个计算复杂的问题分为规模较小、计算简单的小问题求解,然后综合各个小问题,得到最终的答案。大致执行的流程如下:
1.对于一个规模为N的问题,若该问题比较容易解决(比如规模N较小),则直接解决;否则执行下面的步骤。
2.将该问题分解为M的个规模的小问题,这些子问题相互独立,
并且与原问题的形式相同。
3.递归地解这些子问题
4.然后,将各个子问题的解合并得到原问题的解。
使用分治算法需要待求解问题能够转化为若干个小规模的相同问题,通过逐步的划分,能够达到一个易于求解的阶段而直接求解。然后,程序中可以使用递归算法来进行求解。
典型实例
一个袋子里有10个硬币,其中有一枚是假的,并且假币和真币一模一样,肉眼很难分辨出来,目前知道假币比真币的重量轻一点。请问怎么区分哪枚硬币是假币?
1.分析
采用递归分治算法的思想来解决这个问题,大致分析步骤如下:
1)首先为每一枚硬币编号,然后将所有的硬币等分为两份,放在天平的两边。这样就将区分10枚硬币的问题,变为区别两堆硬币的问题。
2)因为假币的重量轻,因此天平较轻的一侧中一定包含假币。
3)再将较轻的一侧的硬币等分为两份,重复上述的做法。
4)直到剩下两枚硬币,可用天平直接找出假币。
2.参考代码
import java.util.Scanner;
public class Divide_conquer {
static final int maxnum=10;
static int FalseCoin(int coin[],int low,int high) {
int i,sum1,sum2,sum3;
int re = 0;
sum1=sum2=sum3=0;
if(low+1==high) {
if(coin[low]<coin[high]) {
re=low+1;
return re;
}else {
re=high+1;
return re;
}
}
if((high-low+1)%2==0) {
for(i=low;i<=low+(high-low) / 2;i++) {
sum1=sum1+coin[i];
}
for(i=low+(high-low) / 2;i<=high;i++) {
sum2=sum2+coin[i];
}
if(sum1>sum2) {
re=FalseCoin(coin, low+(high-low) / 2+1, high);
return re;
}else if(sum1 < sum2) {
re=FalseCoin(coin, low, low+(high-low) /2);
return re;
}else {
}
}else {
for(i=low;i<=low+(high-low /2-1);i++) {
sum1=sum1+coin[i];
}
for(i=low+(high-low) / 2+1;i<=high;i++) {
sum2=sum2 + coin[i];
}
sum3=coin[low+(high-low)/2];
if(sum1>sum2) {
re=FalseCoin(coin, low+(high-low) / 2+1, high);
return re;
}else if(sum1 < sum2){
re=FalseCoin(coin, low, low+(high-low) / 2-1);
return re;
}else {
}
if(sum1+sum3==sum2+sum3) {
re=low+(high-low) /2+1;
return re;
}
}
return re;
}
public static void main(String[] args) {
int [] coin = new int[maxnum];
int i,n;
int location;
System.out.println("分治算法求假硬币问题!");
System.out.println("输入硬币的总的个数:");
Scanner input = new Scanner(System.in);
n=input.nextInt();
System.out.println("请输入硬币的真假:");
for(i=0;i<n;i++) {
coin[i]=input.nextInt();
}
location=FalseCoin(coin, 0, n-1);
System.out.println("在上述"+maxnum+"个硬币中,第"+location+"个硬币是假的!");
}
}
3.结果展示