二分法求解Leetcode 34. Search for a Range

Description

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].


分析

这是leetcode上的一道利用二分法求解的题目,属于medium难度。关键的难点就在于题目限制了时间复杂度为O(logn),也就是说查找的时候必须每次都缩小一半的范围,这也是二分法的精髓所在。定位成功后,还要前后遍历搜素等值的位置,因为目标值可能出现了不止一次,最后靶目标值出现位置的头尾记录下来,用vector返回即可。

具体做法:
  • step1:构造一个find()函数,每次去搜索范围的中间值与target进行比较,若相等则返回此时的position,若target比中间值小,则在前一半继续搜索,若target比中间值大,则在后一半继续搜索,直到找到position或范围只剩下一个元素。

  • step2:将得到的值与target进行比较,若不相等,则返回[-1, -1];若相等,则分别向前向后遍历nums数组,将所有与target值相等的位置找出来,最后返回头和尾。

  • 注:一个细节问题:需要先判断读入的数组是否为空,否则会出现越界的错误!


代码
#include <iostream>
#include <vector>
using namespace std;

int find(vector<int>& nums, int s, int e, int target){
    if (s < e){
        int mid = (s + e) / 2;
        /*分别讨论相等、比target小,比target大三种情况*/ 
        if (target == nums[mid]) return mid;
        else if (target < nums[mid]) return find(nums, s, mid - 1, target);
        else return find(nums, mid + 1, e, target);
    }
    /*只剩一个元素的时候返回*/ 
    else return s;
}

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        vector<int> v;
        /*先判断数组是否为空,防止越界错误!*/ 
        if (nums.empty()){
            v.push_back(-1);
            v.push_back(-1);
            return v;
        }
        int pos = find(nums, 0, nums.size() - 1, target); 
        /*如果没有找到target,则返回[1, 1]*/ 
        if (nums[pos] != target){
            v.push_back(-1);
            v.push_back(-1);
            return v;
        }       
        /*找到目标值所在区域的头尾并返回*/ 
        int pos_big = pos, pos_small = pos;
        while (pos_small > 0 && nums[pos_small - 1] == nums[pos]) pos_small--;
        while (pos_big < nums.size() - 1 && nums[pos_big + 1] == nums[pos]) pos_big++;
        v.push_back(pos_small);
        v.push_back(pos_big);
        return v;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值