二分查找

本文深入讲解二分查找的基础及多种变形应用,包括查找重复元素的第一个和最后一个位置、查找大于或小于指定值的位置等,并提供了具体的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上次面试栽到了二分查找,最简单的问题上,以至于一直不想面对,但是不论怎样,还是要不断成长,不断提升,不会的东西就要不断提升,才能得到真正想要的东西。

好啦,回归正题,二分查找又叫二分查找,它的前提是线性表中的记录必须是有序的,通常常见的就是由小到大排序,查找的基本思想是:在有序表中,取中间记录作为比较对象,若给定值与中间记录的关键字相等,则查找成功;若给定值小于中间记录的关键字,则在中间记录的左半区继续查找;若给定值大于中间记录的关键字,则在中间记录的右半区查找。不断重复上述过程,直到查找成功,或者所有查找区域无记录,查找失败为止。

(1)先来看最基础时候的情况:

int binary_search(int *a, int n, int key)
{
	int low, high, mid;
	low = 0; high = n;
	while (low <= high)
	{
		mid = (low + high) / 2;
		if (key < a[mid])
		{
			high = mid - 1;
		}
		else if (key > a[mid])
		{
			low = mid + 1;
		}
		else
			return mid;
	}
	return 0;
}
(2)当然有很多变形的情况啦,咱们先来看第一种,还是有序数组,但是数字有重复,具体有几个重复不知道,现在要求是要找到第一个出现的位置。

这个题第一次并没有多少想法,甚至记得刷过剑指offer上的内容,当时想着定义一个哈希表,哈希表的键值是字符,而值就是该字符出现的次数,其实题意完全不相关,也是佩服自己当时为什么会那么想,这个题其实可以这么想,既然要找第一次出现的某个数,而且这个数也有可能重复,那我其实让它停止的条件可以是判断第一个小于当前值的下标,那么再判断这个下标加上1是否小于数组的长度,如果小于数组的长度,ok那么最终的输出就是要求的输出。

int mid;
int binary_search(int *a, int n, int key,int &low)
{
	int high;
	low = 0; high = n;
	while (low <= high)
	{
		mid = (low + high) / 2;
		if (key <=a[mid])
		{
			high = mid - 1;
		}
		else
			low = mid + 1;
	}
	return low<n ?low:-1;
}
这样返回的low值就是最终要求的输出,返回的最终值就是加1之后的结果。

(3)第三种情况,找到重复数字最后一个出现的位置。这种情况跟第二种情况同理,其实我们要找的就是第一个大于这个数的位置,那么最终输出的位置就是当前位置减去1,再去判断减去1之后是不是大于-1,大于那么OK。

int mid;
int binary_search(int *a, int n, int key,int &low)
{
	int high;
	low = 0; high = n;
	while (low <= high)
	{
		mid = (low + high) / 2;
		if (key <a[mid])
		{
			high = mid - 1;
		}
		else
			low = mid + 1;
	}
	return (low-1>0 && (a[low-1]==key))?low-1:-1;
}
注意if条件里只要小于mid值那么一直进行这样的操作,所以最后返回的结果就是减去1之后的结果。

(4)查找数组中第一个大于某个数的最小标,其实跟3的情况一样,就是返回的值不一样,返回的值就不需要减去1了,返回为

return low<=n?low:-1;
(5)查找数组中第一个小于某个数的最大标,跟2的情况很像,只是返回值变下,因为(2)的思想最终加了1,所以最终输出的时候记得减去1,输出代码为:

return (low - 1 >= 0) ? low - 1 : -1;
(6)对于判断一个数组中某个数的出现次数,其实是可以调用上述的函数,先求一个数第一次出现的位置记为first,再记录最后一个出现的位置就为last,那么出现的次数就是last-first+1啦。

变形的还有很多很多,学习的道路很长很长,加油吧,参考这篇文章写的,具体也可以参考这篇。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值