🔢 34.在排序数组中查找元素的第一个和最后一个位置
给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target,返回 [-1, -1]。
你必须设计并实现时间复杂度为 O(log n)
的算法解决此问题。
思路
基本思想
如果不要求时间复杂度的话,可以直接使用遍历的方式,从左到右遍历,第一个相等的元素的位置就是开始位置,最后一个不相等的元素的前一个位置就是结束位置,但是本题中强调了时间复杂度
由于是排序数组,所以可以考虑二分查找,先找到相等的元素
找到之后,向左的第一个不相等位置的下一个位置就是开始位置,向右的第一个不相等位置的前一个位置就是结束位置
查找开始和结束位置时需要注意,防止下标越界,到了数组的两端就会强制结束,此时会有两种情况,一种是两端的位置时开始或结束位置
此时nums[right]==target
或者nums[right]==target
数组的两端就是目标,如果只是单纯的到了数组两端,并且数组两端的元素并不是,目标,此时就需要执行left+1
或者right-1
,理解下面的代码即可
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| int left=index,right=index;
//增加left!=0是为了防止下标越界
while(nums[left]==target && left!=0){
left--;
}
//找到了开始位置,判断是到了开头结束还是不相等结束
index=nums[left]==target?left:left+1;
res[0]=index;
//增加right!=nums.size()-1是为了防止下标越界
while(nums[right]==target && right!=nums.size()-1){
right++;
}
//找到了结束位置,判断是到了末尾结束还是不相等结束
index=nums[right]==target?right:right-1;
res[1]=index;
|
while循环结束就需要分情况讨论,直接使用三目运算符分情况
执行流程
代码
根据以上分析,得出以下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
| class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
//找到目标元素的大概位置
int index=binarySearch(nums,0,nums.size()-1,target);
vector<int> res(2,-1);
if(index==-1){
return res;
}else{
int left=index,right=index;
//增加left!=0是为了防止下标越界
while(left!=0&&nums[left]==target){
left--;
}
//找到了开始位置,判断是到了开头结束还是不相等结束
index=nums[left]==target?left:left+1;
res[0]=index;
//增加right!=nums.size()-1是为了防止下标越界
//应该先判断下标是否越界,然后再访问元素
while(right!=nums.size()-1&&nums[right]==target){
right++;
}
//找到了结束位置,判断是到了末尾结束还是不相等结束
index=nums[right]==target?right:right-1;
res[1]=index;
}
return res;
}
int binarySearch(vector<int> &nums,int begin,int end ,int target){
if(begin>end)
return -1;
else{//范围合法
int index=(begin+end)/2;
if(nums[index]>target){//目标在左边
return binarySearch(nums,begin,index-1,target);
}
else if(nums[index]<target){//目标在右边
return binarySearch(nums,index+1,end,target);
}else{//找到目标
return index;
}
}
}
};
|
总结
规定了时间复杂度,则使用二分查找找到对应的位置,然后为了下标越界,到了数组两端强制结束搜索,此时需要判断是到了数组两端强制结束还是遇到了不相等的元素,有下面两种情况:
- nums=[1,1,1,1],target=1,此时因为到了数组两端强制结束
- nums=[1,2,2,3],target=2,此时因为遇到了不相等元素结束