二刷LeetCode--34. 在排序数组中查找元素的第一个和最后一个位置(C++版本)基本二分即可

博客介绍了用二分法查找数组中重复元素最后位置的思路。先找比目标值大一个的元素,二分查找会返回其最左边下标,该位置减一就是目标元素最后位置,而二分法每次返回的是待查找元素最左边下标。

本题的思路在于,找到第一个重复元素的位置并不难,但是怎么找最后一个位置呢,小编想法是找比目标值大的元素,大一个即可,不论原数组中是否存在比目标值大一个的元素,因为二分里面查找是按照中间位置的元素大小与目标值元素大小进行的,因此如果查找比目标值大一的元素,最终就会找到目标值右边一个的位置,然后我们只需要将该位置减一即可。二分法中每次返回的都是待查找元素最左边的下标。

class Solution {
    // 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) 
        { // 区间不为空
            int mid = right + left / 2;
            if (nums[mid] < target)
                left = mid + 1; // 范围缩小到 [mid+1, right]
            else
                right = mid - 1; // 范围缩小到 [left, mid-1]
        }
        return left; // 或者 right+1
    }

public:
    vector<int> searchRange(vector<int> &nums, int target) 
    {
        int start = lower_bound(nums, target); // 使用其中一种写法即可
        if (start == nums.size() || nums[start] != target)
            return {-1, -1};
        // 如果 start 存在,那么 end 必定存在,这里是巧妙的地方
        // target + 1表示不一定非要找到比目标值大 1 的值,而是根据判断会向右移动,
        // 左指针会留在比目标值大一个元素的位置,数值上不一定会大 1 ,但是位置会到想要的地方
        int end = lower_bound(nums, target + 1) - 1;
        return {start, end};
    }
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值