题目: Given a sorted array of integers, find the starting and ending position of a given target value.
Your algorithm’s runtime complexity must be in the order of O(log n).
If the target is not found in the array, return [-1, -1].
For example,
Given [5, 7, 7, 8, 8, 10] and target value 8,
return [3, 4].
思路: 两种方法,一种是在普通的二分查找到目标元素后线性向前和向后探测,找到相同元素的第一个和最后一个位置。第二种方式是找到目标元素后依然采用二分查找的方式向前和向后探测,找到第一个和最后一个位置。第二种方法的边界控制比较复杂。
解法一:
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
vector<int> result(2,-1);
int fir=0;
int sec=nums.size()-1;
int mid;
while(fir<=sec)
{
mid=(fir+sec)/2;
if(nums[mid]>target)
sec=mid-1;
else if(nums[mid]<target)
fir=mid+1;
else
{
auto temp=mid;
while(--temp>=0&&nums[temp]==nums[mid]);
result[0]=(temp+1);
temp=mid;
while(++temp<nums.size()&&nums[temp]==nums[mid]);
result[1]=(temp-1);
return result;
}
}
return result;
}
};
运行通过,但是只击败了11%的代码。
解法二:
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
vector<int> result(2, -1);
int fir = 0;
int sec = nums.size() - 1;
int mid;
while (fir <= sec)
{
mid = (fir + sec) / 2;
if (nums[mid]>target)
sec = mid - 1;
else if (nums[mid]<target)
fir = mid + 1;
else
{
result[0] = searchFirst(nums, fir, mid,target);
result[1] = searchLast(nums, mid, sec,target);
return result;
}
}
return result;
}
int searchFirst(vector<int>& nums, int fir, int sec,int target)
{
int mid;
while (fir <= sec)
{
mid = (fir + sec) / 2;
if (nums[mid] >= target)
sec = mid-1;
else if (nums[mid]<target)
fir = mid + 1;
}
//算法的精髓,返回的并不是mid而是fir,也可以写为return sec+1;
return fir;
}
int searchLast(vector<int>& nums, int fir, int sec,int target)
{
int mid;
while (fir <= sec)
{
mid = (fir + sec) / 2;
if (nums[mid]>target)
sec = mid - 1;
else if (nums[mid] <= target)
fir = mid + 1;
}
//算法的精髓,返回的并不是mid而是sec,也可以写为return fir-1;
return sec;
}
};
解法二的效率在大数据的时候应该效率更高,但是在leetcode上测试时运行时间和解法一的一样。
附加题目: Given a sorted array and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order.
You may assume no duplicates in the array.
Here are few examples.
[1,3,5,6], 5 → 2
[1,3,5,6], 2 → 1
[1,3,5,6], 7 → 4
[1,3,5,6], 0 → 0
思路: 这题考查的和上边的寻找第一个位置比较类似。要时刻注意fir指针和sec指针的变化情况以及跳出循环时它们指向的位置。
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int fir=0,sec=nums.size()-1,mid=0;
while(fir<=sec)
{
mid=(fir+sec)/2;
if(nums[mid]<target)
fir=mid+1;
else if(nums[mid]>target)
sec=mid-1;
else
return mid;
}
//fir会指向插入的位置,sec在fir前一个位置
return fir;
}
};