二分查找算法(随机, 最左, 最右)

本文详细介绍了二分查找算法,包括普通二分查找、查找元素最左出现位置和最右出现位置的实现。通过示例展示了二分查找在猜数游戏中的优势,指出其在有序序列上的高效性,时间复杂度为O(logn)。同时提供了二分查找的代码模板,帮助读者理解和应用二分查找算法。
摘要由CSDN通过智能技术生成


1.定义

二分查找算法是一种效率较高的查找算法,每次查找能把查找范围缩小一半,故也称为折半查找(查找前提:所查区间有序)。

2.举个栗子

现在小明在玩一个猜数游戏,游戏会在(0 ,100]内给定一个数,现在要小明猜这个数,如果小明猜对了,游戏会提示猜对了,游戏结束,如果小明猜错了,它会提示小明的猜的数比答案小了或者大了,要怎么猜才能尽快猜出答案。
现假定答案是69, 我们要在0 - 100 内去猜。
一.如果不看提示

  • 1.最好的情况,小明是欧皇, 第一次就猜69(一发入魂),猜的次数为1。
  • 2.最坏的情况,小明炒鸡倒霉, 前99次都没猜中, 最后一次中了,猜的次数为100。

二.看提示的话
1.小明猜的是3, 假定答案是2的话,他就可以根据提示在(0,3)中猜(极好的情况),但答案是99的话,他就要在(0, 100】中猜了,这样一来,能不能尽快猜中就得看运气了, 在从数学的角度上看,想要尽快猜中靠的不是运运气,而是策略,因此二分查找来啦。

二分查找每次查找的都是中间值,这样一来就能把所查找区间减小一半。
例,还是查69, 第一次二分的查找找中间值50, 比69小了,第二次就从【50, 100】内查找,第二次找中间值75,查找范围编成了(50, 75)范围就又小了一半。 如此反复。 时间复杂度是log100, 大概10 次左右。 而随机查找复杂度充满不确定性(看是欧皇还是非酋),反正比二分大。

1. 普通二分查找

定义

顾名思义,随机查找虽然能查找但所找的元素元素位置随机。

例子 在 a[5]  = {0,1 2 2 2 5 }中找x (x =2), 随机二分查找会找到它第一次找到该元素的位置并返回
查找过程
l = 1,  r = 5, mid; //  l 是第一个元素的下标,r是最后一个元素的下标, mid 是中间元素的下标
mid  =1 + 5/ 2  = 3
a[mid] = 2
a[mid] == x 
返回 3
虽然随机二分查找返回了该元素出现的位置,但该元素不能确定是在序列中第一次出现或最后一次, 即出现次数不定。

随机二分查找函数模板

#include<iostream>
#include<algorithm>
using namespace std;
int a[100], n;// a[]为查找的区间, n为区间元素个数
int find(int x) {//随机查找x
 int l = 1, r = n, mid;
 while (l <= r) {
  mid = (l + r)>>1;
  if (a[mid] == x) return mid;
  a[mid] > x ? r = mid - 1 : l = mid + 1;
 }
 return -1;
}

ps:偶的二分查找的下标是从1开始的,实际使用要看数组的定义情况来确定二分边界。

2.二分查找最左(第一次出现)

即查找序列中该元素第一次出现的位置 原理
在随机查找的基础上做一些修改,在找到它第一次找到该元素的位置时,记录该位置,然后再从该位置之前在进行查找 即在if (a[mid] == x) return mid;中加一句 r = mid - 1;

int findzuo(int x)  {
 int l = 1, r = n, mid, ans = -1;//ans记录出现位置
 while (l <= r) {
  mid = (l + r) / 2;
  if (a[mid] == x) {//找到了
   ans = mid;//记录下出现的位置
   r = mid - 1;//在从【l, mid- 1]中找是否还会出现x
  }
  else if (a[mid] > x) {
   r = mid  - 1;
  }
  else l = mid + 1;
 }
 return ans;
}

二分查找最左模板题

3.二分查找最右(最后一次出现)

即查找序列中该元素第一次出现的位置 原理
在随机查找的基础上做一些修改,在找到它第一次找到该元素的位置时,记录该位置,然后再从该位置之后在进行查找

if (a[mid] == x) return mid;中加一句 l = mid +1;

int findyou(int x) {
 int l = 1, r = n, mid, ans = -1;//ans记录出现位置
 while (l <= r) {
  mid = (l + r) / 2;
  if (a[mid] == x) {//找到了
   ans = mid;//记录下出现的位置
   l = mid +  1;//在从【mid-+1, l]中找是否还会出现x
  }
  else if (a[mid] > x) {
   r = mid  - 1;
  }
  else l = mid + 1;
 }
 return ans;

ps:二分查找是在有序序列的基础上进行的查找,序列必须有序。

4.二分查找练习题

待补

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值