给你一个按照非递减顺序排列的整数数组 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]
算法思想:已知该数组是非递减顺序排列的数组,所以最直接的方法就是暴力法,for循环遍历数组,先找到target,用count计数,再继续找直到第一次出现其他数,并记录其下标,最后返回[i-count,i-1],其时间复杂度是O(n),我们也可以使用双指针法,一个指向下标0,一个指向n-1(虽然时间复杂度不是最好的,但也提供了一个新思路,熟悉了这种方法,在后面的题目中也可以用到)具体代码如下:
class Solution { public: vector<int> searchRange(vector<int>& nums, int target) { int n=nums.size(); int low=0; int high=n-1; if(n==1&&nums[0]==target)//单独分析数组长度为1的情况 return {0,0}; while(low<high){//当low和high相遇时,说明已经遍历完了整个数组 if(nums[low]!=target) low++; if(nums[high]!=target) high--; if(nums[low]==target&&nums[high]==target) return {low,high}; } return {-1,-1}; } };
言归正传,现在题目要求的是时间复杂度为O(logn),看到这个时间复杂度,那我们应该立马想到二分法,这个题目看似和二分查找很相似,都是用二分法找到目标值,但还是有不同之处,首先我们要考虑到三种情况,情况一:target>max或者target<min,如nums={3,4,5},target=1或者target=6,则返回{-1,-1}。情况二:target存在,如nums={3,4,5},target=4,则返回{1,1}。情况三:min<target<max,但target不存在,如nums={4,4,6,7},target=5,则返回{-1,-1}。如果target存在,那我们应该找到target的左右边界,然后返回左右边界的值,具体代码如下:
class Solution { public: vector<int> searchRange(vector<int>& nums, int target) { int left=getLeftBorder(nums, target); int right=getRightBorder(nums, target); if(left==-2 ||right==-2)//情况一 return {-1,-1}; if (right - left >= 0) //情况二 return {left, right}; return {-1,-1};//情况三 } private: int getRightBorder(vector<int>& nums, int target){//找右边界 int getRightBorder=-2; int n=nums.size(); int low=0; int high=n-1; while(low<=high){ int mid=low+(high-low)/2; if(nums[mid]>target) high=mid-1; else{ //因为要找右边界,所以等于或小于都要往右移 low=mid+1; getRightBorder=low; } } return low-1; } int getLeftBorder(vector<int>& nums, int target){ int getLeftBorder=-2; int n=nums.size(); int low=0; int high=n-1; while(low<=high){ int mid=low+(high-low)/2; if(nums[mid]<target) low=mid+1; else{ //因为要找左边界,所以等于或小于都要往左移 high=mid-1; getLeftBorder=high; } } return high+1; } };
代码可能有点繁琐,但逻辑看起来还是不难的,有什么问题大家可以在评论区讨论哦