您的位置:首页 > 其它

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

2015-01-16 21:37 302 查看
题目:有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。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: