0
点赞
收藏
分享

微信扫一扫

【HOT 100 每日一练】 在排序数组中查找元素的第一个和最后一个位置 —— 开区间二分算法

题目

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

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

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

示例 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 <= 105 -109 <= nums[i] <= 109 nums 是一个非递减数组 -109 <= target <= 109

分析:

根据题目给定一个非递减的数组,在其中查找目标值target,那我们应该想到二分算法,并且题目要求的时间复杂度为 O(log n) ,而二分算法的时间复杂度正好是 O(log n) ; 具体的,由于是查找target的范围,而二分算法只能查找一个值,因此我们可以调用两次二分算法:

  • 第一次查找target的开始位置start,如果start等于n(即nums数组没有target)或查找的nums[start] != target,则表示nums中没有target,返回{-1, -1};
  • 否则进行第二次查找,我们可以查找比target大于1的值的开始位置start_big,而start_big - 1就是target的结束位置end,返回{start, end}。

AC代码:

class Solution {
    int lowerBound(vector<int>& nums, int target) {
        int n = nums.size();
        int left = -1, right = n;
        while (left + 1 < right) {
            int mid = (right - left) / 2 + left;
            if (nums[mid] >= target) {
                right = mid;
            } else {
                left = mid;
            }
        }
        return right;
    }
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        int start = lowerBound(nums, target);
        if (start == nums.size() || nums[start] != target) {
            return {-1, -1};
        }
        int end = lowerBound(nums, target + 1) - 1;

        return {start, end};
    }

};
举报

相关推荐

0 条评论