1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| /** * 【假币问题】 有n枚硬币,其中有一枚是假币,已知假币的重量较轻。现只有一个天平,要求用尽量少的比较次数找出这枚硬币。 * * 【分析问题】 将n枚硬币分成相等的两部分: 1.当n为偶数时,将前后两部分,即 1...n/2 * 和n/2+1...0,放在天平的两端,较轻的一端里有假币,继续在较轻的这部分硬币中用同样的方法找出假币: 2.当n为奇数时,将前后两部分,即 * 1...(n-1)/2 和 (n+1)/2+1...0,放在天平的两端,较轻的一端里有假币,继续在较轻的这部分硬币中用同样的方法找出假币; * 若两端重量相等,则中间的硬币,即第 (n+1)/2 枚硬币是假币。 * * 【调用方式】 int cs[] = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2,} * getCounterfeitCoint(cs, cs[0], cs[cs.length-1]) * * @param coins * @param first * @param last * @return */ static int getCounterfeitCoin(int coins[], int first, int last) {
int firstSum = 0, lastSum = 0, i;
if (first == last - 1) { // 只剩两枚 if (coins[first] < coins[last]) return first;
return last; }
if ((last - first + 1) % 2 == 0) { // 偶数枚 for (i = first; i < (first + last) / 2; i++) firstSum += coins[i];
for (i = first + (last - first) / 2 + 1; i < last + 1; i++) lastSum += coins[i];
if (firstSum < lastSum) return getCounterfeitCoin(coins, first, first + (last - first) / 2); else return getCounterfeitCoin(coins, first + (last - first) / 2 + 1, last);
} else { // 奇数枚
for (i = first; i < first + (last - first) / 2; i++) firstSum += coins[i];
for (i = first + (last - first) / 2 + 1; i < last + 1; i++) lastSum += coins[i];
if (firstSum < lastSum) return getCounterfeitCoin(coins, first, first + (last - first) / 2 - 1); else if (firstSum > lastSum) return getCounterfeitCoin(coins, first + (last - first) / 2 - 1, last); else return (first + last) / 2;
} }
|