二分查找
目录
- 1 介绍
- 2 例题引入
- 3 “左闭右闭”写法
- 4 “左闭右开”写法
1 介绍
二分查找适用于从一个递增或递减的有序数列中查找某一个值
因此,使用二分查找的条件是:
- 用于查找的内容从逻辑上来看是有序的
- 查找的数量只能是一个而不是多个
在二分查找中,目标元素的查找区间的定义十分重要,不同的区间的定义写法不一样
二分查找通常有两种写法:
- 左闭右闭[left,right]
- 左闭右开[left,right)
2 例题引入
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。 https://leetcode.cn/problems/binary-search/description/
给定一个 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
整个数组是有序的、递增的
- 选择数组中间的数组和需要查找的目标值比较
- 如果相等,直接返回下标
- 如果不相等
- 如果中间的值大于目标值,则中间数字及其右边的所有数字都大于目标值, 全部排除
- 如果中间的值小于目标值,则中间数字及其左边的所有数字都小于目标值, 全部排除
当数组长度是奇数的时候,中间的数字的左右两边的数字的个数是一样的;当数组长度是偶数的时候,中间的数字的左右两边的数字的个数是不一样的。
这不影响怎么排除的问题,无非是多排除一个数字或者少排除一个数字
- 真正影响的是中间那个数字到底该不该加入下一次的查找中,也就是边界问题
3 “左闭右闭”写法
注意:
- while循环中left和right的关系,是left≤right还是left<right
- 迭代过程中middle和right的关系,是right=middle-1还是right=middle
int serch(int[] nums,int target){int size=sizeof(nums)/sizeof(int);//数组长度int left=0;int right=size-1;//定义了target在左闭右闭的区间内while(left<=right){int middle=left+(right-left)/2;if(nums[middle]>target){right=middle-1;}else if(nums[middle]<target){left=middle+1;}else{return middle;}}return -1;}
4 “左闭右开”写法
每次查找的区间在 [left, right)
int serch(int[] nums,int target){int size=sizeof(nums)/sizeof(int);//数组长度int left=0;int right=size;//左闭右开,不包含right指向的那个位置while(left<right){int middle=left+(right-left)/2;if(nums[middle]>target){right=middle;//左闭右开}else if(nums[middle]<target){left=middle+1;}else{return middle;}}return -1;}