
704. 二分查找
704. 二分查找
题目描述:
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。 

解题思路:
本题数组是有序的,具有二段性,因此我们可以使用二分算法来解决这个问题
值得注意的是:当left和right不断向中间移动的过程中,left和right可能指向同一个位置,而这个位置需要判断,因此我们的循环条件为left<=right
解题代码:
class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left=0;
        int right=nums.size()-1;
        while(left<=right)
        {
            int mid=left+(right-left)/2;
            if(nums[mid]==target) return mid;
            if(nums[mid]>target) right=mid-1;
            if(nums[mid]<target) left=mid+1;
        }
        return -1;
        }
}; 
34. 在排序数组中查找元素的第一个和最后一个位置
34. 在排序数组中查找元素的第一个和最后一个位置
题目描述:
给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target,返回 [-1, -1]。
你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。

解题思路:
本题我们利用二分来解决左右端点的问题,首先left和right肯定有的
我们通过一个示例来了解本题:[1,2,3,3,3,4,5]
查找左端点:我们这里用t来代替target(这样比较好叙述)
- 二分的思路操作:我们可以将上述示例分为两个部分,因为我们现在查找左端点,因此我可以将示例分为【[1,2],[3,3,3,4,5]】
 
- 当x<t时,处于【1,2】这个区间,left=mid+1
 - 当x>=t时,处于【3,3,3,4,5】这个区间,right=mid(这里不能等于mid-1,因为如果mid=0,right=-1会越界)
 
- 细节处理:
 循环条件:
- left<right √
 - left<=right ×
 我们选择那种呢?我们来讨论一下:
- 有结果
 - 全大于t(t1),right一直向左走,最后right为left结束,如果是left<=right会死循环
 - 全小于t(t2),left一直向右走,最后left在right右边结束
 以此我们只能选择第一种不能选择第二种!
求中间的操作:
- left+(right-left)/2 ×
 - left+(right-left+1)/2 √
 我们考虑一下极端情况就可以知道了!当只剩下两个元素的时候:
第一种没有问题,第二种mid=0+2/2=1,当进行left+1操作的时候会发生越界
查找右端点:
- 二分的思路操作:我们可以将上述示例分为两个部分,因为我们现在查找左端点,因此我可以将示例分为【[1,2,3,3,3].[4,5]】
 
- 当x<=t时,处于【1,2,3,3,3】这个区间,left=mid
 - 当x>t时,处于【4,5】这个区间,right=mid-1
 
- 细节处理:
 循环条件:
- left<right √
 - left<=right ×
 还是选择left<right
求中间的操作:
- left+(right-left)/2 √
 - left+(right-left+1)/2 ×
 我们考虑一下极端情况就可以知道了!当只剩下两个元素的时候:
第一种当mid=0+1/2=0时,right=mid-1越界,第二种没有问题
解题代码:
class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        //特殊情况处理一下
        if(nums.size()==0)return {-1,-1};
        int left=0,right=nums.size()-1;
        vector<int> ret;
        //查找左端点
        while(left<right)
        {
            int mid=left+(right-left)/2;
            if(nums[mid]<target)left=mid+1;
            if(nums[mid]>=target)right=mid;
        }
        //当left==right时就是结果
        if(nums[left]!=target)return {-1,-1};
        else ret.push_back(left);
        //查找右端点
        left=0,right=nums.size()-1;
        while(left<right)
        {
            int mid=left+(right-left+1)/2;
            if(nums[mid]<=target)left=mid;
            if(nums[mid]>target)right=mid-1;
        }
        if(nums[right]!=target)return {-1,-1};
        else ret.push_back(right);
        return ret;
    }
}; 



















![[Spring] Spring5——IOC 简介(二)](https://img-blog.csdnimg.cn/acdd080d850849fcb6e456c3168fb3e6.png)





