34. 在排序数组中查找元素的第一个和最后一个位置(LeetCode热题100)

发布于:2025-02-24 ⋅ 阅读:(17) ⋅ 点赞:(0)

题目来源:

34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣(LeetCode)

题目内容:

给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。

如果数组中不存在目标值 target,返回 [-1, -1]

你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。

示例 1:

输入:nums = [5,7,7,8,8,10], target = 8
输出:[3,4]

示例 2:

输入:nums = [5,7,7,8,8,10], target = 6
输出:[-1,-1]

示例 3:

输入:nums = [], target = 0
输出:[-1,-1]

思路分析:

  • 二分法

  • 自己写这个函数lower_bound(nums,target) 

代码实现:

class Solution {
    //自己写一个函数 lower_bound  返回最小的满足nums[i]>=target 的下标
    int lower_bound(vector<int> &nums,int target){
        //二分法(闭区间) 实现
        int n=nums.size();
        int left =0;
        int right =n-1;
        while(left<=right){
            int mid=left+(right-left)/2;
            if(nums[mid]>=target) right=mid-1;
            else left=mid+1;
        }
        return left;
    }

public:
    vector<int> searchRange(vector<int>& nums, int target) {
        int start=lower_bound(nums,target);
        if(start==nums.size()||nums[start]!=target){
            //数组为空或者数组中没有target
            return {-1,-1};
        }
        int end=lower_bound(nums,target+1)-1;//美!
        return {start,end};
    }
};

题目心得:

  1. 自己写这个函数lower_bound(nums,target)    代码如下   来源:34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣(LeetCode)
     

    // lower_bound 返回最小的满足 nums[i] >= target 的下标 i
    
        // 如果数组为空,或者所有数都 < target,则返回 nums.size()
    
        // 要求 nums 是非递减的,即 nums[i] <= nums[i + 1]
    
        int lower_bound(vector<int>& nums, int target) {
    
            int left = 0, right = (int) nums.size() - 1; // 闭区间 [left, right]
    
            while (left <= right) { // 区间不为空
    
                // 循环不变量:
    
                // nums[left-1] < target
    
                // nums[right+1] >= target
    
                int mid = left + (right - left) / 2;
    
                if (nums[mid] >= target) {
    
                    right = mid - 1; // 范围缩小到 [left, mid-1]
    
                } else {
    
                    left = mid + 1; // 范围缩小到 [mid+1, right]
    
                }
    
            }
    
            // 循环结束后 left = right+1
    
            // 此时 nums[left-1] < target 而 nums[left] = nums[right+1] >= target
    
            // 所以 left 就是第一个 >= target 的元素下标
    
            return left;
    
        }
    
  2. 注意!if(start==nums.size()||nums[start]!=target)
                //数组为空或者数组中没有target
             

  3. 注意!int end=lower_bound(nums,target+1)-1;
               //这段代码是点睛之笔