上力扣原题目链接:704. 二分查找 - 力扣(LeetCode)
为了方便大家查看,我这边列出题目描述
题目描述:
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
示例:
输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4
输入: nums = [-1,0,3,5,9,12], target = 2
输出: -1
解释: 2 不存在 nums 中因此返回 -1
输入: nums = [5], target = 5
输出: 0
首先先解释一下为什么力扣没有主函数,这是为了让大家更加有效率的刷题而设计的,我们只需在它给出来的类函数里面利用它已知的条件书写就可以了。
(本题的前提是数组内没有重复的元素,否则返回的下标不是唯一的)
解法:
先把数组元素sort排序一下,按升序排序。如果输入样例已经排好了,则可以省略这个步骤。
先设三个变量l,r,mid并初始化,分别代表最初数组的最左边,最右边和最中间的数组下标,这里因为数组的下标是从0开始的,所以l=0,r=nums.size()-1,mid=(l+r)/2。
因为需要不断的把数组二分化,再进行查找,所以mid赋值和查找需要在循环里进行。这里的循环条件是l的下标不大于r。
循环内面临三种情况,先对比是否nums[mid]==target,如果nums[mid]的值等于我们要查找的值,就直接返回mid下标;如果不等于,则再进行下面的两种情况对比。
- 一种是nums[mid]>target,由于数组是升序,则表示target在mid下标的左边,这时候应该把搜索区间选为左半边的数组,则需要把r改为mid-1,然后再进行循环查找。
- 一种是nums[mid]<target,由于数组是升序,则表示target在mid下标的右边,这时候应该把搜索区间选为右半边的数组,则需要把l改为mid+1,然后再进行循环查找。
关于为什么循环条件是l<=r
因为如果不设置l<=r,那么当数组中只有一个元素时,l=0,r=0,这时候不会进入循环,而会返回一个-1,无法通过所有案例。
话不多说,我们直接看代码
class Solution {
public:
int search(vector<int>& nums, int target) {
int l=0,r=nums.size()-1;
int mid;
while(l<=r){
mid=(l+r)/2;
if(nums[mid]==target){
return mid;
}else if(nums[mid]<target){
l=mid+1;
}else if(nums[mid]>target){
r=mid-1;
}
}
return -1;
}
};
为什么要选择二分查找?
二分查找的好处就是不用一个一个去对比是否为要求元素,而是把数组逐渐分成两半去寻找
,时间复杂度从最原始的O(n)降到了O(logn)