每日OJ题_算法_二分查找②_力扣34. 在排序数组中查找元素的第一个和最后一个位置

发布时间:2024年01月24日

目录

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

解析代码


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

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]

提示:

  • 0 <= nums.length <= 10^5
  • -10^9?<= nums[i]?<= 10^9
  • nums?是一个非递减数组
  • -10^9?<= target?<= 10^9
class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {

    }
};

解析代码

非递减,就是数组往后都是大于或者等于的元素,用暴力解法就是找到随便一个端点元素,然后往前往后线性遍历,极端时间复杂度还是O(N),这里用进阶二分的套路(等下总结)

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        int size = nums.size();
        if(size == 0) // 处理边界
            return {-1, -1}; //返回一个vector里两个整数的方式

        int left = 0, right = size - 1; // 找左端点
        while(left < right) // 一定是小于
        {
            int mid = left + (right - left) / 2; // 元素个数是偶数时,中点是中间的左边
            if(nums[mid] < target) // 左端点肯定不在左边
                left = mid + 1;
            else
                right = mid; // 可能自己是左端点,可能左端点还在左边
        }
        if(nums[left] != target) // 没有端点的情况
            return {-1, -1};
        int tmp = left; // 记录左端点

        right = size - 1; // 找右端点,left不用重置
        while(left < right)
        {
            int mid = left + (right - left + 1) / 2; // 元素个数是偶数时,中点是中间的右边
            if(nums[mid] > target) // 右端点肯定右在左边
                right = mid -1;
            else
                left = mid; // 可能自己是右端点,可能右端点还在右边
        }
        return {tmp, right};
    }
};

以后二分大部分题目都是这个进阶二分的套路,套路就是这样的了(注意两个while的比较):

        int left = 0, right = size - 1; // 找左端点
        while(left < right) // 一定是小于
        {
            int mid = left + (right - left) / 2; // 元素个数是偶数时,中点是中间的左边
            if(nums[mid] < target) // 左端点肯定不在左边
                left = mid + 1;
            else
                right = mid; // 可能自己是左端点,可能左端点还在左边
        }
        if(nums[left] != target) // 没有端点的情况
            return {-1, -1};
        int tmp = left; // 记录左端点

        right = size - 1; // 找右端点,left不用重置
        while(left < right)
        {
            int mid = left + (right - left + 1) / 2; // 元素个数是偶数时,中点是中间的右边
            if(nums[mid] > target) // 右端点肯定右在左边
                right = mid -1;
            else
                left = mid; // 可能自己是右端点,可能右端点还在右边
        }
        return {tmp, right};
文章来源:https://blog.csdn.net/GRrtx/article/details/135740273
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。