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

题目描述:

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

你的算法时间复杂度必须是 O(log n) 级别。

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

示例 1:

输入: nums = [5,7,7,8,8,10], target = 8
输出: [3,4]

示例 2:

输入: nums = [5,7,7,8,8,10], target = 6
输出: [-1,-1]

 

要完成的函数:

vector<int> searchRange(vector<int>& nums, int target) 

说明:

1、这道题给定一个vector和一个target,vector中装着升序的一个数组,比如[5,7,7,8,8,10],

要求找到target比如8,在vector中的起始位置和结束位置。

算法时间复杂度要求是O(logn)级别的。

如果在vector中找不到target,那么返回[-1,-1]。

2、这道题又是一道二分法的题目,不过是二分法的一个变种。

按照二分法的思路,我们可以这样子设计:

①首先根据二分法找到vector中的某个target元素,这个元素是一串target元素中的某一个,记这个元素的索引是med。

②接着从vector的头部开始,到med-1这个位置,根据二分法找到某个元素——元素不是target,但是元素的下一个元素是target。

这个元素的下一个元素,也就是一串target元素中的第一个。

③接着从med+1这个位置开始,到vector的尾部结束,根据二分法找到某个元素——元素不是target,但是元素的前一个元素是target。

这个元素的前一个元素,也就是一串target元素中的最后一个。

总体思路如上,当然其中要有一些边界情况的处理,比如②中找不到这个元素怎么办,vector是[8,8,8,8,8],target是8,我们根本找不到一个不是8的元素。

还有,不存在target的边界情况,也要特殊处理一下。

代码如下:(附详解)

    vector<int> searchRange(vector<int>& nums, int target) 
    {
        int left=0,right=nums.size()-1,med,t1;//t1是临时变量
        while(left<=right)//用二分法找到某个target元素
        {
            med=(left+right)/2;
            if(nums[med]==target)
                break;
            else if(nums[med]>target)
                right=med-1;
            else
                left=med+1;
        }
        if(left>right)return {-1,-1};//如果找不到target元素,返回[-1,1]
        
        left=0,right=med-1;//更新left为vector的头部索引,right为med-1
        while(left<=right)//用二分法找到我们想要的元素
        {
            med=(left+right)/2;
            if(nums[med]!=target&&nums[med+1]==target)//满足这个退出条件,nums[med]就是我们要的元素
                break;
            if(nums[med]<target)//不满足退出条件,且当前nums[med]小于target,那么更新left,继续循环
                left=med+1;
            else if(nums[med]==target)//不满足退出条件,且nums[med]是target,那么更新right,继续循环
                right=med-1;
        }
        if(left>right)//如果找不到我们想要的元素,left大于right了,那么med才是target元素的起始位置
            t1=med;
        else//如果找得到我们想要的元素,那么med+1才是target元素的起始位置
            t1=med+1;
        
        left=med+1,right=nums.size()-1;//更新left为med+1,right为vector的尾部索引
        while(left<=right)//用二分法找到我们想要的元素
        {
            med=(left+right)/2;
            if(nums[med]!=target&&nums[med-1]==target)//满足退出条件就退出
                break;
            if(nums[med]>target)//同上
                right=med-1;
            else if(nums[med]==target)//同上
                left=med+1;
        }
        if(left>right)//如果找不到我们想要的元素,那么med才是target元素的结束位置
            return {t1,med};
        else//如果找得到,那么med-1才是target元素的结束位置
            return {t1,med-1};
    }

上述代码实测8ms,beats 97.36% of cpp submissions。

猜你喜欢

转载自www.cnblogs.com/king-3/p/9465187.html
今日推荐