leetcode 34. Search for a Range (binary search std::lower_bound)

56 篇文章 0 订阅
53 篇文章 0 订阅

写在前面

一个简单的二分查找的题目,惯常的二分查找然后循环查找边界虽然可以AC,但是是肯定不符合要求的,所以必须从二分查找上找答案。

题目描述

Given an array of integers sorted in ascending order, find the starting and ending position of a given target value.

Your algorithm’s runtime complexity must be in the order of O(log n).

If the target is not found in the array, return [-1, -1].

For example,
Given [5, 7, 7, 8, 8, 10] and target value 8,
return [3, 4].

思路分析

我们通常使用二分查找的方式就是简单地在指定范围内去查找一个数,而我们知道,C++ lower_bound和upper_bound是C++语言中的二分查找泛型算法(当然也有binary_search,这里不讨论)。前者返回区间内大于等于目标值的第一个位置的迭代器,不存在则返回end()迭代器,后者返回区间内大于目标值的第一个位置的迭代器,不存在同样返回end()迭代器(这里是upper_bound的直观解释,正式的解释可以查阅文档)。对于本题,我们使用这两个函数,就可以轻易解出满足要求的题解。当然,这部分的关键代码是lower_bound的实现,lower_bound本身是二分查找的变形,很简单,这种写法可以作为二分查找的模板写法。

lower_bound(非模板的实现)

// 这里返回下标位置

int lower_bound(vector<int>& nums, int target) {
    int left = 0;
    int right = nums.size();
    while(left<right) {
        auto mid = left + (right-left)/2; // 这种写法可以防止left+right 过大导致的溢出
        if(target>nums[mid])left = mid+1;
        else right = mid;
    }
    return left;
}

// AC 解

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {

        auto iter = std::lower_bound(nums.begin(),nums.end(),target);
        if(iter==nums.end()||*iter!=target) return {-1,-1};
        auto left = iter-nums.begin();
        auto siter = std::upper_bound(iter,nums.end(),target);
        auto right = siter-nums.begin()-1;
        return {left,right};
        // 排好序的数组 一般是二分查找
        // binary search
        // lower_bound
        if(nums.size()==0) return {-1,-1};
        int left = 0,right = nums.size();
        // lower_bound
        while(left<right) {
            auto mid = left + (right-left)/2;
            if(target<=nums[mid]) right = mid;
            else left = mid+1;
        }
        if(left == nums.size()||nums[left]!=target) return {-1,-1};
        int retLeft = left;
        right = nums.size();
            while(left<right) {
            auto mid = left + (right-left)/2;
            if(target+1<=nums[mid]) right = mid;
            else left = mid+1;
        }
        if(left == retLeft) return {retLeft,retLeft};
        int retRight = left-1;
        return {retLeft,retRight};
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值