一、二分查找是什么?
二分查找也称折半查找,是在一组有序(升序/降序)的数据中查找一个元素,它是一种效率较高的查找方法。注意必须说有序的序列才行
二、例题
1.leetcode上的 704. 二分查找
给定一个
n
个元素有序的(升序)整型数组nums
和一个目标值target
,写一个函数搜索nums
中的target
,如果目标值存在返回下标,否则返回-1
。
示例 1:输入:nums
= [-1,0,3,5,9,12],target
= 9 输出: 4 解释: 9 出现在nums
中并且下标为 4示例 2:
输入:nums
= [-1,0,3,5,9,12],target
= 2 输出: -1 解释: 2 不存在nums
中因此返回 -1提示:
- 你可以假设
nums
中的所有元素是不重复的。n
将在[1, 10000]
之间。nums
的每个元素都将在[-9999, 9999]
之间。
代码如下:
#include <bits/stdc++.h>
using namespace std;
int fun(int nums[],int size,int x){
int left=0,right=size-1;
//这个地方是left<=right
while(left<=right){
int mid=left+(right-left)/2;
if(nums[mid]>x){
right=mid-1;
}else if(nums[mid]<x){
left=mid+1;
}else{
return mid;
}
}
return -1;
}
int main() {
//[-1,12]左闭右闭
int a[6]={-1,0,3,5,9,12};
int target=9;
int size=sizeof(a)/sizeof(a[0])-1;//普通数组只能用sizeof(a)/sizeof(a[0])求数组长度
cout<<fun(a,size,target);
return 0;
}
注意:
1.while(left<=right),这个地方是while(left<=right)不是while(left<right)。这个地方要根据条件来规定,如果是[-1,12]左闭右闭这种情况就是left<=right,因为左闭右闭两端是可以相等的,举个例子如果区间里面只有一个元素1即[1,1],根据左闭右闭那么两端就是相等的。如果是[-1,12)左闭右开这种两端不能相等就只能是left<right。这种就是数学里面的区间问题。
2.if(nums[mid]>x)right=mid-1;这个地方是mid-1还是mid主要看区间的定义。如果是[-1,12]左闭右闭这种情况就是mid-1,如果是[-1,12)左闭右开就是mid,因为if(nums[mid]>x)中已经判断了nums[mid]>x所以下一步更换区间时就一定是mid-1,如果是mid可能会出现死循环,举个例子[0,1]找0.5,mid=left,然而left=mid这样会一直死循环。
总结
1.二分查找主要注意序列是否有序
2.查看给定序列的范围。例如是[-1,12]左闭右闭还是(-1,12),根据范围写出对应的代码