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

文章描述了一种优化的二分查找算法,用于在给定的非递减整数数组中快速找到目标值的起始和结束位置,时间复杂度为O(logn),并通过示例展示了具体实现过程。
摘要由CSDN通过智能技术生成

题目要求

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

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

你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。

示例 1:

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

示例 2:

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

示例 3:

输入:nums = [], target = 0
输出:[-1,-1]

提示:

  • 0 <= nums.length <= 105
  • -109 <= nums[i] <= 109
  • nums 是一个非递减数组
  • -109 <= target <= 109

可以和二分查找一样,先将该元素查找出来,然后再将左指针和右指针都赋值为该指针的值,通过该元素的位置,判断左指针的左侧是否还继续等于该值,右指针的右侧是否还等于该值,且左指针和右指针都不可以越界,需要加上一个判断条件。

对于我之前在做二分查找类题目的时候,改变条件的时候老是将左/右指针直接变化为mid的位置上,事实上,如果当mid位置上的元素不等于target的时候,mid位置上的元素就属于一个已知状态,可以直接舍去这个位置的值,直接将left/right = mid-1/+1,这样子循环结束的条件就可以不需要很麻烦的判断,且所有可能的元素都能够在这个过程中被遍历到。

还有就是vector数组,我在下面返回的数组是临时创建了有一个数组,然后再给他赋值,其实可以直接创建一个临时数组然后返回的,比如return vector<int>{1,2,3,4(里面放应该存储的临时数组对的元素)}。

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) 
    {
        if(nums.size()<1)
        {
            vector<int>a(2);
            a[0] = -1;
            a[1] = -1;
            return a;
        }
        int left = 0, right = nums.size()-1, mid = (left+right)/2;
        //目标有可能只有一个,那么left可能就只等于right
        //如果判断条件是left<right,那么小小大的情况就判断不出来(是无限的死循环),小大大能判断出来
        //但是这样判断就不知道边界点和目标值的大小了,所以应该是当找到大于和小于时,此时的mid是已知的,所以可以直接利用mid
        while(left < right)
        {
            if(nums[mid]>target)
            {
                right = mid-1;
                mid = (left+right)/2;
            }
            else if(nums[mid]<target)
            {
                left = mid+1;
                mid = (left+right)/2;
            }
            else
            {
                break;
            }
        }
        if(left >= right-1 && nums[mid]!=target)
        {
            vector<int>a(2);
            a[0] = -1;
            a[1] = -1;
            return a;
        }
        left = mid;
        right = mid;
        // cout<<mid;
        //数组有越界的风险
        // while(left>=0 && nums[left--] == target);
        // while(right<nums.size() && nums[right++] == target);
        while(left>0 && nums[left-1] == target)
        {
            left--;
        }
        while(right < nums.size()-1 && nums[right+1] == target)
        {
            right++;
        }

        vector<int>a(2);
        a[0] = left;
        a[1] = right;
        //或者直接返回vector<int>{left, right(里面直接放元素)}
        return a;
    }
};

以上代码思路仅限个人观点,如有其他想法和思路,欢迎大家一起交流进步,谢谢大家

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值