在排序数组中查找元素的第一个和最后一个位置(力扣34题)底层原理

这道题一开始百思不得其解,看了好几种和好多遍解答。终于领悟精髓。

题目如图:
​​​​​​在这里插入图片描述

拿到题目粗略分析思路

  1. 时间复杂度=>二分查找法
  2. 用两个二分查找法分别定位开始和结束位置
  3. 查找结果可能性分析

具体分析思路(自底部而上逐层分析)

1.查找结果可能性分析(同时确定二分查找法区间是 左闭右开 还是 左闭右闭)

选择 左闭右开

结果分析(定义-1 为未能查找到的结果):

  1. 目标值不在数组中 返回(-1,-1)
  2. 目标值在数组中 返回(左边界,右边界-1)
    此步骤完成代码如下:
    vector<int> searchRange(vector<int>& nums, int target) {
        int leftBoard = searchLeftBoard(nums,target);    
        int rightBoard = searchRightBoard(nums,target);
        if(-1 == leftBoard || -1 == rightBoard)
         {return{-1,-1};}
        else  {return  {leftBoard,rightBoard-1};}
        }

2.写左右边界查找算法(以左边界 为例)

1.写出二分查找法基本架构(左闭右闭)(基本功闭着眼都应该能写出来)

int searchLeftBoard(vector<int>& nums, int target){
    int l = 0;
    int r = nums.size();
    while( l < r){
        int mid = (r - l )/2 + l;
        if( target > nums[mid]){
            l = mid + 1;
        }else if(target == nums[mid]){
        //暂且空着
        }else{
            r = mid;   
        }
    }
    return  ;//暂且空着
}

2.添加一个左边界变量 初始为-1,返回结果为-1,表明未查找到结果

int searchLeftBoard(vector<int>& nums, int target){
    int l = 0;
    int r = nums.size();
    int leftBoard = -1;//添加
    while( l < r){
        int mid = (r - l )/2 + l;
        if( target > nums[mid]){
            l = mid + 1;
        }else if(target == nums[mid]){
        //暂且空着
        }else{
            r = mid;   
        }
    }
    return  leftBoard ;//添加
}

3.返回边界值

在判断 target 和 nums[mid]相等时 更新 l 或 r 并 返回边界值。

  1. 确立边界:r = mid 如果是确定右边界 应该是 l = mid + 1;
  2. 返回边界值 : leftBoard = r 这里会有很多人疑问 为啥不是 用 l 赋值 原因是:这里的 l 和 r 是左边界的 l 和 r 。每次 target 和 nums[mid] 相等时,都会更新边界值,即将 l 和 r 赋值给边界值。
    该部分代码如下:
int searchLeftBoard(vector<int>& nums, int target){
    int l = 0;
    int r = nums.size();
    int leftBoard = -1;
    while( l < r){
        int mid = (r - l )/2 + l;
        if( target > nums[mid]){
            l = mid + 1;
            
        }else if(target == nums[mid]){
            r = mid; 
            leftBoard = r; 
        }else{
            r = mid; 
             
        }
    }
    return leftBoard;
}

整体代码如下:

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        int leftBoard = searchLeftBoard(nums,target);    
        int rightBoard = searchRightBoard(nums,target);
        if(-1 == leftBoard || -1 == rightBoard)
         {return{-1,-1};}
        else  {return  {leftBoard,rightBoard-1};}
        }
 

int searchLeftBoard(vector<int>& nums, int target){
    int l = 0;
    int r = nums.size();
    int leftBoard = -1;
    while( l < r){
        int mid = (r - l )/2 + l;
        if( target > nums[mid]){
            l = mid + 1;
            
        }else if(target == nums[mid]){
            r = mid; 
            leftBoard = r; 
        }else{
            r = mid; 
             
        }
    }
    return leftBoard;
}
int searchRightBoard(vector<int>& nums, int target){
    int l = 0;
    int r = nums.size();
    int rightBoard = -1;
    while( l < r){
        int mid = (r - l )/2 + l;
        if( target < nums[mid]){
            r = mid ; 
            rightBoard = l;  
        }else if(target == nums[mid]){
            l = mid + 1;
            rightBoard = l;
        }else{
            l = mid + 1;
        }
    }
    return rightBoard;
}

};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值