Find First and Last Position of Element in Sorted Array

博客围绕在按升序排序的整数数组中,查找给定目标值的起始和结束位置展开。介绍了题目要求,算法复杂度需满足一定顺序。给出两种解题思路,一是用STL内置方法,二是自己实现,可采用二分查找。还展示了STL、二分查找实现lower_bound、二分查找加前后探索三种代码实现方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1,题目要求

Given an array of integers nums 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(logn).

If the target is not found in the array, return[-1, -1].

Example 1:
Input: nums = [5,7,7,8,8,10], target = 8
Output: [3,4]

Example 2:
Input: nums = [5,7,7,8,8,10], target = 6
Output: [-1,-1]

给定按升序排序的整数数组,找到给定目标值的起始位置和结束位置。

算法的运行时复杂度必须是O(logn)的顺序。

2,题目思路

对于这道题,题目是在一个已经排序的数组内,找到对应元素的第一个和最后一个出现的位置。

如果我们使用STL内置的方法,即:

  • lower_bound
  • upper_bound

问题可以得到轻松的解决。

而如果我们自己实现,也可以实现类似的功能,不过题目要求时间复杂度为O(logn),因此,对于查找而言,满足条件的自然是二分查找

而在二分查找上,因为我们不是找到这个元素,而是为了找到第一个比target小的元素,因此,判定条件部分为:

while(low <= high){
	int mid = low + (high - low)/2;
    if(nums[mid] < target)
    	low = mid+1;
    else
        high = mid-1;
}

另外一种思路则是在于,因为这个数组是有序的,因此,我们要查找的target要么不在数组中,要么只有一个。
而如果在数组中有多个target出现,则它们一定是连续出现的。这样,我们只需要使用二分查找的办法在target中找到对应的元素位置,然后分别向前和向后探索,找到target的边界,也可以得到最终的结果。

3,代码实现

1,STL

int x = []() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    return 0;
}();

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        auto it1 = std::lower_bound(nums.begin(), nums.end(), target);
        auto it2 = std::upper_bound(nums.begin(), nums.end(), target);
        if (it1 != nums.end() && *it1 == target) 
            return {it1 - nums.begin(), it2 - nums.begin() - 1};
        return {-1, -1};
    }
};

2,二分查找实现lower_bound

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        int left = myLower_bound(nums, target, 0, nums.size()-1);
        int right = myLower_bound(nums, target+1, 0, nums.size()-1)-1;
        //之所以要添加left < nums.size(),是为了排除nums = []的情况
        //因为这种情况下,left = 0,nums.size() = 0,因此可以排除
        if(left < nums.size() && nums[left] == target)
            return {left, right};
        return {-1,-1};            
    }
private:
    int myLower_bound(vector<int>& nums, int target, int low, int high){
        while(low <= high){
            int mid = low + (high - low)/2;
            if(nums[mid] < target)
                low = mid+1;
            else
                high = mid-1;
        }
        return low;
    }
};

3,二分查找+前后探索

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        int index = binarySearch(nums, target, 0, nums.size()-1);
        vector<int> res {-1,-1};
        if(index == -1)
            return res;
        else
        {
            int left = index;
            int right = index;
            while(left >= 0 && nums[left] == target )   left--;
            while(right<=nums.size()-1 && nums[right] == target)    right++;
            res[0] = left+1, res[1] = right-1;
        }
        return res;
    }
private:
    int binarySearch(vector<int>& nums, int target, int low, int high) {
        while(low <= high){
            int mid = low + (high - low)/2;
            if(nums[mid] == target)
                return mid;
            else if(nums[mid] < target)
                low = mid+1;
            else
                high = mid-1;  
        }
        return -1;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值