寻找假银币是一个非常有趣的智力题目,寻找假银币的大意如下:
现在有8枚银币,其中一枚是假币。但是,从外观和做工上无法分辨哪枚是真币哪枚是假币,只知道假币的重量要比真币稍轻。则要求仅用一个天平,如何以最少的步骤寻找到假银币?
1. 寻找假银币算法
可以采用递归分治的思想来求解这个问题,操作步骤如下:
(1)首先为每个银币编号,然后可以将所有的银币等分为两份,放在天平的两边。
(2)因为假银币的分量较轻,因此天平较轻的一侧中一定包含假银币。
(3)再将较轻的一侧中的硬币等分为两份,重复上述做法。
(4)直到剩下两枚硬银币,可用天平直接找出假银币来。
这种方法在银币个数比较多时便显出了优势。照此思路编写寻找假银币问题求解的算法如下:
static int falseCoin(int coin[],int low,int high){ int i,sum1,sum2; int re=0; sum1=sum2=0; if(low+1==high){ if(coin[low]<coin[high]){ re=low+1; return re; }else{ re=high+1; return re; } } //如果n是偶数 if((high-low+1)%2==0){ //记录前一半的重量 for(i=low;i<low+(high-low+1)/2;i++){ sum1+=coin[i]; } //记录后一半的重量 for(i=low+(high-low+1)/2;i<=high;i++){ sum2+=coin[i]; } if(sum1<sum2){ re = falseCoin(coin,low,low+(high-low+1)/2-1); }else if(sum1>sum2){ re = falseCoin(coin,low+(high-low+1)/2,high); } }else{ //n为奇数 //记录前一半的重量 for(i=low;i<low+(high-low)/2;i++){ sum1+=coin[i]; } //记录后一半的重量 for(i=low+(high-low)/2+1;i<=high;i++){ sum2+=coin[i]; } if(sum1<sum2){ re = falseCoin(coin,low,low+(high-low)/2-1); }else if(sum1>sum2){ re = falseCoin(coin,low+(high-low)/2+1,high); }else{ re=low+(high-low)/2+1; return re; } } return re; }
2. 寻找假银币求解完整代码
package com.cn.suanfaquti; import java.util.Scanner; public class FalseCoin { static final int MAXNUM=30; //最大硬币数 static int falseCoin(int coin[],int low,int high){ int i,sum1,sum2; int re=0; sum1=sum2=0; if(low+1==high){ if(coin[low]<coin[high]){ re=low+1; return re; }else{ re=high+1; return re; } } //如果n是偶数 if((high-low+1)%2==0){ //记录前一半的重量 for(i=low;i<low+(high-low+1)/2;i++){ sum1+=coin[i]; } //记录后一半的重量 for(i=low+(high-low+1)/2;i<=high;i++){ sum2+=coin[i]; } if(sum1<sum2){ re = falseCoin(coin,low,low+(high-low+1)/2-1); }else if(sum1>sum2){ re = falseCoin(coin,low+(high-low+1)/2,high); } }else{ //n为奇数 //记录前一半的重量 for(i=low;i<low+(high-low)/2;i++){ sum1+=coin[i]; } //记录后一半的重量 for(i=low+(high-low)/2+1;i<=high;i++){ sum2+=coin[i]; } if(sum1<sum2){ re = falseCoin(coin,low,low+(high-low)/2-1); }else if(sum1>sum2){ re = falseCoin(coin,low+(high-low)/2+1,high); }else{ re=low+(high-low)/2+1; return re; } } return re; } public static void main(String[] args) { int[] coin=new int[MAXNUM]; int i,n,result; System.out.println("分治法求解假银币问题!"); System.out.print("请输入银币总个数:"); Scanner input = new Scanner(System.in); n=input.nextInt(); System.out.print("请输入银币重量:"); for(i=0;i<n;i++){ coin[i]=input.nextInt(); } result = falseCoin(coin,0,n-1); //求解 System.out.printf("在上述%d个银币中,第%d个银币是假的!",n,result); } }
程序运行结果如下:
分治法求解假银币问题! 请输入银币总个数:7 请输入银币重量:2 2 1 2 2 2 2 在上述7个银币中,第3个银币是假的!