題目:有n個小球,其中有一個比其他的都要重,已知有一個天平,怎麼用最少的次數把小球找出來?
個人代碼如下:
#include <iostream>
#include <numeric>
using namespace std;
int GetAbnormalBall(int a[], int begin, int end, int &count)
{
if(begin == end)
return a[begin];
int Num = (end - begin) + 1;
int HalfNum = Num / 2;
++count;
int fweight = accumulate(a + begin, a + begin + HalfNum, 0);
int bweight = accumulate(a + begin + HalfNum, a + begin + 2 * HalfNum, 0);
if(Num % 2 != 0) //剩餘數量是奇數的時候
{
if(fweight == bweight)
return a[end];
else if(fweight > bweight)
return GetAbnormalBall(a, begin, begin + HalfNum - 1, count);
else
return GetAbnormalBall(a, begin + HalfNum, end, count);
}
else if(fweight > bweight) //剩餘數量是偶數的時候
return GetAbnormalBall(a, begin, begin + HalfNum - 1, count);
else if(fweight < bweight)
return GetAbnormalBall(a, begin + HalfNum, end, count);
else
return -1; //表示不存在
}
int main()
{
//int a[] = {4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
int count = 0;
int a[] = {1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1};
int len = sizeof(a)/sizeof(int);
cout<< GetAbnormalBall(a, 0, len - 1, count) <<endl;
cout<< "查找的次數: " << count <<endl;
}
輸出:
個人小結:
以上的方法是用了二分查找的方式。思路是:
1)如果剩餘的總數是奇數的話,平均分成兩半,那麼就有一個多出來,
如果這兩半的數量相等,那麼多出來那個一定是那個重的小球。如果不相等,找出重的那邊繼續切成兩半進行遞歸。
2)如果剩餘的總數是偶數的話,就可以平均的分成兩半。找出重的那邊繼續切分,依此不斷遞歸,直到找到那個重的小球,或者重的小球不存在。
3)如果重的小球不存在,那麼返回-1。