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};
}
};