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

2023.5.22

题目描述:

        这道题是数组系列第五题的一个增难版,注意这里题目说的是非降序,而数组系列第五题说的是升序,区别就是非降序就有可能有重复的元素了。要求时间复杂度是log n ,就是非得用二分法来做了。我的思路是使用两次二分法,分别找到满足条件的第一个元素位置和最后一个元素位置。直接上代码:

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) 
    {
        vector<int> ans;
        int i = 0;
        int j = nums.size()-1;
        //定义指向满足条件的第一个元素位置和最后一个元素位置
        int first = -1;
        int last = -1;
        
        //找出满足条件的第一个元素位置
        while(i <= j)
        {
            int k = (i+j)/2;
            if(nums[k] < target) i = k + 1;
            else if(nums[k] > target) j = k - 1;
            else
            {
               first = k;
               j = k -1;
            }
        }

        i = 0;
        j = nums.size()-1; //将左右两指针置0
        //找出满足条件的最后一个元素位置
        while(i <= j)
        {
            int k = (i+j)/2;
            if(nums[k] < target) i = k + 1;
            else if(nums[k] > target) j = k - 1;
            else
            {
               last = k;
               i = k + 1;
            }
        }
        return {first,last};
    }
};

         虽然满足时间复杂度的要求,但是应该是绕了远路的,有机会再更新一个更优的解。


2023.9.3

        时隔三个月,二刷。 本题第一反应想出了个O(n)时间复杂度的解法,代码比之前简单很多,分别求出start和end的值即可。 代码如下:

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        int start = -1;
        int end = -1;
        for(int i=0; i<nums.size(); i++)
        {
            if(nums[i] == target)
            {
                start = i;
                break;
            }
        }
        //起始位置在数组的终点 或者 起始位置之后无target值了
        if(start == nums.size()-1 || nums[start+1] != target) return {start,start}; 

        for(int i=start+1; i<nums.size(); i++)
        {
            if(nums[i] == target) end = i;
        }
        return {start,end};
    }
};

优化:

        题目要求O(log n)时间复杂度的方法,可以用二分法进行优化:用二分法找到target值,再左右延申查找左右边界。代码如下:

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        int left = 0;
        int right = nums.size()-1;
        int start = -1;
        int end = -1;
        while(left <= right)
        {
            int mid = (left + right) / 2;
            if(nums[mid] == target)
            {
                start = mid;
                end = mid;
                while(start>0 && nums[start-1] == target) start--; //寻找左边界
                while(end<nums.size()-1 && nums[end+1] == target) end++; //寻找右边界
                break;
            }
            else if(nums[mid] < target) left = mid + 1;
            else right = mid - 1;
        }
        return {start,end};
    }
};

        ps: 三个月前写的二分法真的是又臭又长😂


2023.9.27

        刷力扣HOT100又遇到了,三刷。 这次第一反应就是二分法了,秒过。

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        int left = 0;
        int right = nums.size()-1;
        while(left <= right)
        {
            int mid = (left+right)/2;
            if(nums[mid] < target) left = mid + 1;
            else if(nums[mid] > target) right = mid - 1;
            else
            {
               left = mid;
               right = mid;
               while((right+1)<nums.size() && nums[right+1]==target) right++;
               while((left-1)>=0 && nums[left-1]==target) left--;
               return{left,right};
            }
        }
        return{-1,-1};
    }
};

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值