减治法求八硬币问题,Java实现

来源:互联网 发布:php 字节数组转字符串 编辑:程序博客网 时间:2024/06/06 10:01

问题描述:在八枚外观相同的硬币中,有一枚是假币,并且已知假币与真币的重量不同,但不知道假币与真币相比较轻。可以通过一架天平来任意比较两组硬币,设计一个高效的算法来检测出这枚假币。本文的代码将问题简化,默认假币比真币轻,并且将8硬币扩展为n枚硬币(n任取),利用减治法来求解问题。

主要的思想:如果是硬币的数量为偶数,平分硬币称重,取较轻的一组再称重,如果硬币为奇数,默认取出第一个硬币,然后按照偶数个称重,如果两组重量相等,那么假币为取出的一个,如果不等,那么轻的这组再次称重。递归这个过程,直到找出假币。

import java.util.Random;import java.util.Scanner;public class Ncoins {public int[] coins;Ncoins(int n){coins = new int[n];for (int i = 0; i < coins.length; i++) {coins[i] = 1;}Random r = new Random();coins[r.nextInt(n)] = 0;}public void show() {for (int i = 0; i < coins.length; i++) {System.out.print(coins[i] + " ");}}/** * 判断是否为奇数 * @param n * @return */public boolean isOdd(int n) {if(n % 2 == 0) return false;else return true;}/** * 求和 * @param first * @param last * @return */public int getSum(int first, int last) {int sum = 0;for(int i = first; i <=  last; i++) {sum += coins[i];}return sum;}/** * 核心算法 * @param first * @param last * @return */public int findFakeCoin(int first,int last) {int sum1,sum2,sum3;float a = (float)(last - first) / 2;int b = (int) (last - a); //取中间的数组下标if(isOdd(last - first + 1)) {sum1 = getSum(first + 1,b);sum2 = getSum(b + 1, last);sum3 = coins[first];if(sum1 == sum2) return first;else if(sum1 < sum2) return findFakeCoin(first + 1, b);else return findFakeCoin(b + 1, last);}else {sum1 = getSum(first,b);sum2 = getSum(b + 1,last);if(sum1 > sum2) return findFakeCoin(b + 1,last);if(sum1 < sum2) return findFakeCoin(first,b);}return -1;}public static void main(String[] args) {System.out.println("输入硬币个数:");Scanner s = new Scanner(System.in);Ncoins n = new Ncoins(s.nextInt());n.show();int i = n.findFakeCoin(0, n.coins.length - 1);System.out.println("位置:" + i +" 为假币");}}


运行结果(位置从0开始)




算法课的作业