SWUST OJ#1010(折半查找的实现)

目录

前言引入

计算mid应该注意的细节

题目 

代码演示

小结


前言引入

二分查找的原理大家可以回想一下高中数学中我们用二分法求函数的零点的思路!现在回到编程领域,我们要在一个升序的区间【left,right】,要中查找一个数find,遵循如下原则(mid=left+(right-left)/2)
1.如果mid大于find,则下一次在区间【left,mid-1】中查找,因为f(mid)>find,所以查找区间的右边界right=mid-1

2.如果mid小于find,则下一次在区间【mid+1,right】中查找,因为f(mid)<find,所以查找区间的左边界left=mid+1

3.如果mid恰好等于find,输出mid,如果数组是从下标为0开始存储的,mid+1便是要查找数据所在的位置,如果数组是从下标为1开始存储的,mid便是要查找数据所在的位置

然后一直重复着这个过程,直到中间找到数据或者left>right便退出循环~

计算mid应该注意的细节

我们在每进行一次判断前,都要重新计算一下mid,然而许多人都是用mid=(left+right)/2去计算,其实这个有时候是不好的,因为如果基数很大,left+right可能会超过long long 型的数据范围,而导致数据精度的丢失,如果用mid=left+(right-left)/2去计算,则可以在一定程度上避免这个问题~ 而防爆数据范围的方法有许多,有待大家去慢慢发现,博主在这里就不做过多的阐述了~

题目 

许多人明明代码对了,为什么还会wa呢? (๑•̌.•̑๑)ˀ̣ˀ̣这便是对这个题目中位序的错误理解,他不同于位置(位序=位置-1),所以5的位序便是0,92的位序便是10.

代码演示

#include <iostream>
#include <algorithm>
using namespace std;
int sum = 0, a[10005];
int f(int left, int right, int find)
{
	int zhong;
	while (left <= right)
	{
		sum++;
		zhong = left + (right - left) / 2;
		if (a[zhong] > find)
			right = zhong - 1;
		else if (a[zhong] < find)
			left = zhong + 1;
		else
			return zhong;
	}
	return -1;
}
int main()
{
	int i, find, n;
	cin >> n;
	for (i = 0; i < n; i++) cin >> a[i];
	cin >> find;
	cout << f(0, n - 1, find) << endl << sum;
	return 0;
}

小结

其实这是二分查找的简单版本的一种表现形式,但实际中我们会遇到像查找一个数据,如果数组中有相同的数据返回最后(最前面)一个数据的位置等问题,这里博主强烈安利下面朋友的这篇博客,二分查找与二分答案

希望对各位有所帮助~

🥂(❁´◡`❁)您的点赞➕评论➕收藏⭐是作者创作的最大动力🤞

  • 10
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

詹小友

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值