二分查找之天平稱重,稱出最重的小球

題目:有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。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章