折半查找代码的缺陷,看看你的代码是否存在该问题

94 阅读2分钟

一、引言

  不知道大家是否写过这样的一串代码,理论上能够计算满足该条件的所有数值,实际上过大的数却无法运算,从而导致错误的结果。今天我在写代码的时候无意察觉的一些东西。我在执行第一串代码的时候没有问题,但是若是把查找的值放大之后就没办法准确运行了。

int binary_search(int arr[], int k, int sz)
{
	int left = 0;
	int right = sz - 1;
	while (left <= right)
	{
		int mid = (left + right) / 2;
		//int mid = left+(right- left) / 2;
			if (arr[mid] < k)
			{
				left = mid + 1;
			}
			else if (arr[mid] > k)
			{
				right = mid - 1;
			}
			else
			{
				return mid;
			}
	}
	return -1;
}

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int k = 0;
	scanf("%d", &k);
	int sz = sizeof(arr) / sizeof(arr[0]);
	int ret = binary_search(arr, k, sz);
	if (ret == -1)
	{
		printf("找不到\n");
	}
	else
	{
		printf("找到了,下标是%d", ret);
	}
	return 0;
}
//上述代码的缺陷:在于int mid = (left + right)/2;的值如果很大就会造成结果错误
//修改成下列形式int avg = num1 + (num2 - num1)/2则可以避免这一情况
int main()
{
	int num1 = 4563165847674;
	int num2 = 4563165847676;
	//int avg = (num1+num2)/2;
	int avg = num1 + (num2 - num1) / 2;
	printf("%d\n", avg);
	return 0;
}

运行结果如下,显然不可能为一个负数。 image.png

二、思路讲解

  大部分在看到我修改的代码是难以理解的,但是结合我的这张图就可以理解了。
首先:如果我们求的是a柱+b柱的和的一半的话,直接叠在一起再减半,会突破这个数值的界限。导致后续的计算出现错误。所以我们需要尽量降低它的高度(也就是数值大小)。

其次:我们可以观察到图中,我是讲b柱中大于a柱的高度的那部分划去一半安在了a的上面,最后形成了a和b一样的高度的柱形图。

最后:我们给自己的大脑一点点的思考时间就会明白,这样就跟脑筋急转弯一样的思路。 image.png ps(大家可以尝试一下定义成long long类型的扩大数值上限的方法)