##2023/3/3 刷算法的第二天
针对力扣的704题:本题是二分查找的基本使用!在此需要注意二分查找的基本特点:
1.数列基本有序;
2.数列数据内容不可重复。
此题一试便知可以暴力求解:
但是暴力求解的时候,看样列知道还有一种可能是vector为空,此种情况应该单独拿出来讨论,不然就会指针越界报错!
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
//暴力求解
int left=-1,right=-1;
if(!nums.size())
{
return {left,right};
}
for(int i=0;i<=nums.size()-1;i++)
{
if(nums[i]==target)
{
left=i;
i=nums.size();
}
}
for(int j=nums.size()-1;j>=0;j--)
{
if(nums[j]==target)
{
right=j;
j=-1;
}
}
return {left,right};
}
};
求解方法二:二分查找法:
使用二分查找的时候就把左右分开来找,时间复杂度依旧是O(log n)的。
算法思想(以找左边界为例):思考,原二分查找算法是分为三种情况的,那我们在分开找的时候就可以想想如何利用这三种情况一次就找到?比如找左边的时候,就可以先二分,然后一直向左走。那么如何一直向左走呢?方法就是改变判断方式——即我们只需要将原来二分查找的大于和等于合二为一,条件成立就使得right变为mid-1,以此即可实行一直左走的目的。右边也是如此,代码如下:
class Solution {
public:
//二分查找
vector<int> searchRange(vector<int>& nums, int target) {
int LL=last_Left(nums,target);
int RR=last_Right(nums,target);
return {LL,RR};
}
private:
int last_Left(vector<int>&nums,int target) // 左边
{
int left=0,right=nums.size()-1;
int Left=-1;
while(left<=right)
{
int mid=(left+right)/2;
if(nums[mid]>=target) //大或者是等都向左走
{
right=mid-1;
if(nums[mid]==target)
Left=mid;
}
else
left=mid+1;
}
return Left;
}
int last_Right(vector<int>&nums,int target)
{
int left=0,right=nums.size()-1;
int Right=-1;
while(left<=right)
{
int mid=(left+right)/2;
if(nums[mid]<=target) //小或者是等都向右走
{
left=mid+1;
if(nums[mid]==target)
Right=mid;
}
else
right=mid-1;
}
return Right;
}
}
;
当然此种写法也有不足之处,既是内存使用过多。不过对于现在的水平,能写出来就已经心满意足了,日后当能力大涨之后又来弥补吧!