Leetcode-34在排序数组中查找元素的第一个和最后一个位置

二分搜索

class Solution {
public:
    int BinarySearch_first(vector<int>& nums,int target){
        int left=0,right=nums.size()-1;//要点nums.size()-1和nums.size()
        while(left<=right){//要点:<= 和 <
            int mid=left+(right-left)/2;//避免两数直接相加超出范围
            if(nums[mid]<target){
                left = mid + 1;
            }else if(nums[mid]>target){
                right= mid - 1;
            }else{
                right=mid-1;//向左收缩
            }
        }
        //此时 left 和 right 的位置关系是 [right, left]
        if(left != nums.size()){//这个地方顺序很重要,如果left越界下一个判断条件会报错
            if(nums[left]==target) return left;
        }
        return -1;
    }

    int BinarySearch_last(vector<int>& nums,int target){
        int left=0,right=nums.size()-1;
        while(left<=right){
            int mid=left+(right-left)/2;
            if(nums[mid]<target){
                left = mid + 1;
            }else if(nums[mid]>target){
                right= mid - 1;
            }else{
                left=mid+1;//向右收缩
            }
        }
        if(right != -1){
            if(nums[right]==target) return right;
        }
        return -1;
    }

    vector<int> searchRange(vector<int>& nums, int target) {
        if (nums.empty()) {
            return vector<int>{-1, -1};
        }
        int leftindex = BinarySearch_first(nums,target);
        int rightindex = BinarySearch_last(nums,target);
        return vector<int>{leftindex,rightindex};
    }
};
class Solution {
public:
    int BinarySearch_first(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){
                right=mid;
            }else if(nums[mid]>target){
                right=mid;
            }else{
                left=mid+1;
            }
        }
        if(nums[left] == target){
            return left;
        }
        return -1;
    }

    int BinarySearch_last(vector<int>& nums, int target){
        int left=0;
        int right=nums.size()-1;
        while(left<right){
            int mid=right-(right-left)/2;//特别注意:向上取整
            if(nums[mid]==target){
                left=mid;
            }else if(nums[mid]>target){
                right=mid-1;
            }else{
                left=mid;
            }
        }
        if(nums[right] == target){//每次循环结束left==right不需要区分
            return right;
        }
        return -1;
    }

    vector<int> searchRange(vector<int>& nums, int target) {
        if(nums.empty()){
            return vector<int>{-1,-1};
        }
        int leftindex=BinarySearch_first(nums,target);
        int rightindex=BinarySearch_last(nums,target);
        return vector<int>{leftindex,rightindex};
    }
};
class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        int leftindex=BinarySearch(nums,target-1);
        int rightindex=BinarySearch(nums,target)-1;
        if(leftindex==nums.size()||nums[leftindex]!=target){
            return vector<int> {-1,-1};
        }
        return vector<int> {leftindex,rightindex};
    }

    int BinarySearch(vector<int>& nums, int target){
        int left=0,right=nums.size();
        while(left<right){
            int mid=left+(right-left)/2;
            if(nums[mid]>target){
                right=mid;
            }else{
                left=mid+1;
            }
        }
        return left;
    }
};

—————————————————————————————

二分搜索细节整理
while (left <= right) 一般是简单问题用,在循环体里能找到答案以后退出。
在退出循环的时候 left = right + 1,即 right 在左,left 在右;
while (left < right) 复杂问题用,把答案留到退出循环以后,再判断。
在退出循环的时候,有 left == right 成立
第二种方法优势在于边界问题,需要考虑的细节最少

—————————————————————————————

二分搜索问题整理
while(left<=right)
1.寻找目标元素出现的位置
如果等于,就可以直接返回 return mid;
如果严格大于,就往右边查找 left=mid+1;
如果严格小于,就往左边查找 right=mid-1;
2.寻找目标元素出现的第一个位置
如果等于,区间就向左收缩 right=mid-1;
如果严格大于,就往右边查找 left=mid+1;
如果严格小于,就往左边查找 right=mid-1;
3.寻找目标元素出现的最后一个位置
如果等于,区间就向右收缩 left=mid+1;
如果严格大于,就往右边查找 left=mid+1;
如果严格小于,就往左边查找 right=mid-1;

//此时 left 和 right 的位置关系是 [right, left]
//注意此时left是第一次元素出现的位置
if(left != nums.size()){//这个地方顺序很重要,如果left越界下一个判断条件会报错
//需要单独判断left是否越界
	if(nums[left]==target) return left;
}
return -1;
//同理
if(right != -1){
	if(nums[right]==target) return right;
	}
return -1;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值