• 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。

  • 相关阅读:
    阿里云ECS安全组之新手不得不面对的问题
    【云栖风向标】VOL.3:阿里云:对不起_这个官司我不服!
    Linux全自动安装wdcp面板脚本
    “程序员”和“码农”究竟有什么区别?
    安卓新标准出台_告别乱弹窗_你的手机真会省电么?
    16年程序员平均工资122478元_你拖后腿了没?
    6.5世界环境日!来聊聊那些你想不到的环保黑科技?
    小扎曝Facebook北极数据中心图片_最先进数据中心都建在哪?
    js之单例模式
    js 之 call 、 apply
  • 原文地址:https://www.cnblogs.com/chenjx85/p/9465187.html
Copyright © 2020-2023  润新知