法1:左右闭区间
class Solution {
public:
int search(vector<int>& nums, int target)
{
int begin=0;int end=nums.size()-1;
while(begin<=end)
{
int mid=(begin+end)/2;
if(target<nums[mid])
{
end=mid-1;
}
if(target>nums[mid])
{
begin=mid+1;
}
if(target==nums[mid])
{
return mid;
}
}
return -1;
}
};
需要注意的是循环条件为begin<=end,因为在end=begin的时候,也是有情况发生的
在边界改变的时候,不让begin=mid,end=mid而是begin=mid+1,end=mid-1.是因为此时的nums[mid]已经检测过了,不=target
2,左闭右开
class Solution {
public:
int search(vector<int>& nums, int target)
{
int begin=0;int end=nums.size();
while(begin<end)
{
int mid=(begin+end)>>1;
if(target>nums[mid])
{
begin=mid+1;
}
if(target<nums[mid])
{
end=mid;
}
if(target==nums[mid])
{
return mid;
}
}
return -1;
}
};
其实跟第一个是可以等价变换的,因为第二种方法的end多加了一个1,所以在end变化的时候不用再减去1
根据思想去理解,begin=end时没有意义,因为刚开始的时候就是end为空,所以在相等的时候就没有意义
法1:暴力解法
class Solution {
public:
int removeElement(vector<int>& nums, int val)
{
int size=nums.size();
for(int i=0;i<size;i++)
{
if(nums[i]==val)
{
for(int j=i;j<size-1;j++)
{
nums[j]=nums[j+1];
}
size--;
i--;
}
}
return size;
}
};
时间复杂度比较高,循环套循环,思路也比较简单,重要的是下一个方法,双指针的应用
法2:双指针
class Solution {
public:
int removeElement(vector<int>& nums, int val)
{
int slow=0;
for(int fast=0;fast<nums.size();fast++)
{
if(nums[fast]!=val)
{
nums[slow]=nums[fast];
slow++;
}
}
return slow;
}
};
双指针,一个快指针,一个慢指针
快指针,用来遍历整个数组
满指针,用来找到等于val的数在数组中的下标
然后用快指针指向的数组中的数,替换慢指针指向的数(也就是替换掉等于val的数)
可以用画图更好的理解