704二分查找
最容易理解和记录的是左闭右开;
如果是闭区间那么r=m-1,l=m+1;
哪边开区间,就可以往里走,左开的话l=m ,右开的话右=m ,同时要注意l和r的初始值防止越界。
//左闭右开
class Solution {
public:
int search(vector<int>& nums, int target)
{
int l=0;
int r=nums.size();
while(l<r)
{
int m=(l+r)/2;
if(target>nums[m]) l=m+1;
else if(target<nums[m]) r=m;
else return m;
}
return -1;
}
};
//左开右闭
class Solution {
public:
int search(vector<int>& nums, int target)
{
int l=-1;
int r=nums.size()-1;
while(l<r)
{
int m=(l+r+1)/2;
if(target>nums[m]) l=m;
else if(target<nums[m]) r=m-1;
else return m;
}
return -1;
}
};
//左闭右闭
class Solution {
public:
int search(vector<int>& nums, int target)
{
int l=0;
int r=nums.size()-1;
while(l<=r)
{
int m=(l+r)/2;//int m=(l+r+1)/2;
if(target>nums[m]) l=m+1;
else if(target<nums[m]) r=m-1;
else return m;
}
return -1;
}
};
如果不考虑数组越界的问题 问题会变得更简单
while (l < r)
{
int mid = l + r >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
return l;
while (l < r)
{
int mid = l + r + 1 >> 1;
if (check(mid)) l = mid;
else r = mid - 1;
}
return l;
35搜索插入位置
class Solution {
public:
int searchInsert(vector<int>& nums, int target)
{
int l=0;
int r=nums.size()-1;
while(l<=r)
{
int m=(l+r)>>1;
if(nums[m]>target) r=m-1;
else if(nums[m]<target) l=m+1;
else return m;
}
return r+1;
}
};
其实是一样的 左闭右闭 r本身可以去到 所以返回r+1;左闭右开本身r取不到,所以返回r本身,本身就可以表示下一个位置。
34. 在排序数组中查找元素的第一个和最后一个位置
开区间写法
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target)
{
if(nums.empty()) return{-1,-1};
int l=0;
int r=nums.size();
while(l<r)
{
int m=l+(r-l)/2;
if(nums[m]>=target) r=m;
else l=m+1;
}
if(l==nums.size()||nums[l]!=target) return{-1,-1};
int left=l;
l=0;
r=nums.size();
while(l<r)
{
int m=l+(r-l)/2;
if(nums[m]<=target) l=m+1;
else r=m;
}
int right=r-1;
vector<int>res;
res.push_back(left);
res.push_back(right);
return res;
}
};
写法是用的左闭右开的写法 找左边界就从右往左逼近,找右边界就从做往右逼近
但是很奇怪 会出现越界的问题。需要加一个l==nums.size();
27移除元素
有点没搞懂题意,一开始以为条件里写个slow++就完事了;
class Solution {
public:
int removeElement(vector<int>& nums, int val)
{
int slow=0;
for(int i=0;i<nums.size();i++)
{
if(nums[i]!=val)
{
nums[slow++]=nums[i];
}
}
return slow;
}
};
26删除有序数组中的重复项
和上一题差不多 但是slow初始值要设为1;
class Solution {
public:
int removeDuplicates(vector<int>& nums)
{
int slow=1;
for(int i=1;i<nums.size();i++)
{
if(nums[i]!=nums[i-1])
{
nums[slow++]=nums[i];
}
}
return slow;
}
};