1.简介
1.二分查找的思路简单易懂,较难的是如何处理查找过程中的边界条件,当较长时间没写二分查找的时候就容易忘记如何处理边界条件。
2.只有多写代码,多做笔记就不易忘记边界条件
2.算法思路
正常查找都是从头到尾查找一个数字是否在数组中
二分查找适用于已经有序的数组,利用有序的这个性质,定义两个指针,left指向头,right指向尾,定义一个mid为头尾指针的平均值。
首先选择mid位置的数字和目标值比较
中间值与target相等直接返回这个数字的下标即可
如果不相等
如果mid位置的数字数字大于目标值,则mid位置的数字向右的所有数字都大于target,全部排除,让mid-1变为新的尾部
如果mid位置的数字数字小于目标值,则mid位置的数字向左的所有数字都小于target,全部排除,让mid+1成为新的头部
最后left>right的话说明该数组中没有target这个数字
示例
给定一个 n
个元素有序的(升序)整型数组 nums
和一个目标值 target
,写一个函数搜索 nums
中的 target
,如果目标值存在返回下标,否则返回 -1
。
示例1
nums=[-1,0,3,5,9,] target=9 输出4,因为数组中有9,且其下标尾4
下面给出查找的过程
mid处为3,3<9,所以让mid+1成为新的头部(left=mid+ 1)
如下图
5<9,再次缩小左边界
找到了,返回mid下标4
示例2
nums=[-1,0,3,5,9,] target=2 输出-1,因为数组中没有2
同理给出过程
3>2,缩小右边界 right=mid-1
此时,新的mid为(0+1)/2=0
-1<2,让left=mid+1
此时0<2,让left=mid+1
left>right.说明整个数组中没有目标值,返回-1
3.实现代码
代码如下
int BinarySearch(vector<int>& arr, int target)
{
if (arr.size() < 1)
return -1;
int left = 0, right =arr.size() - 1;
while (left <= right)
{
int mid = left + ((right - left) >> 1);
if (arr[mid] > target)
right = mid - 1;
else if (arr[mid] < target)
left = mid + 1;
else
return mid;
}
//没找到
return -1;
}
4.二分查找的特点
时间复杂度:O(logN)
空间复杂度:O(1)
适用于查找有序的数组
5.简单测试
测试代码
int BinarySearch(vector<int>& arr, int target)
{
if (arr.size() < 1)
return -1;
int left = 0, right =arr.size() - 1;
while (left <= right)
{
int mid = left + ((right - left) >> 1);
if (arr[mid] > target)
right = mid - 1;
else if (arr[mid] < target)
left = mid + 1;
else
return mid;
}
//没找到
return -1;
}
int main()
{
vector<int> arr = { -1,0,3,5,9 };
cout << BinarySearch(arr, 9) << endl;
cout << BinarySearch(arr, 2) << endl;
return 0;
}
测试结果
6.Leetcode相关练习题
704. 二分查找 - 力扣(LeetCode)
35. 搜索插入位置 - 力扣(LeetCode)
367. 有效的完全平方数 - 力扣(LeetCode)
69. x 的平方根 - 力扣(LeetCode)
34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣(LeetCode)
下面这道题思想类似于二分查找,是高频面试题之一
240. 搜索二维矩阵 II - 力扣(LeetCode)