day1:二分法、双指针法
704. 二分查找
二分查找
根据区间定义有两种解法(注意循环条件)
方法一:左闭右闭
class Solution {
public:
int search(vector<int>& nums, int target) {
int low=0;
int high = nums.size()-1;
int mid = (low+high)/2;
while(low<=high)
{
if(target == nums[mid])
{
return mid;
}
else if (target > nums[mid])
{
low = mid + 1;
mid = (low + high) / 2;
}
else if(target < nums[mid])
{
high = mid - 1;
mid = (low + high) / 2;
}
}
return -1;
}
};
方法二:左闭右开
class Solution {
public:
int search(vector<int>& nums, int target) {
int left=0;
int right=nums.size();
int mid = left+(right-left)/2;
while(left<right)//左闭右开
{
if(nums[mid]>target)
{
right = mid;
mid = (left+right)/2;
}
else if(nums[mid]<target)
{
left = mid+1; //如果没有加1出现死循环
mid = (left+right)/2;
}
else
{
return mid;
}
}
return -1;
}
};
第二题 移除元素
需要注意的是数组的地址是连续的,所以不可能把某个元素单独删除,只能对该地址的值进行覆盖
在本题条件下,方法有三种:
1.暴力解法,利用双重for循环,遍历每个元素,如果遇到和目标值相同的元素,则从该位置的下一个位置开始将后面的元素全部向前移动一位并覆盖该位置的值
2.快慢指针法,一层循环,快的指针寻找不等于目标值的元素,慢的指针记录这些位置并存储
3.相向指针法,左指针向右遍历寻找不等于目标值的元素,右指针向左遍历寻找等于目标值的元素,一旦寻找到一个立即用不等于的元素覆盖另一边等于的元素,此外,元素位置会被打乱,注意前置递增和后置递增的区别,此处使用原因。
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
//双向指针
int left=0;
int right = nums.size()-1;
while(left<=right) //nums = [3,2,2,3], val = 3
{
//查找左边不等于val的元素
while(left<=right&&nums[left]!=val) //left=0 < right =3 nums[0]=val ----- left=2
{
++left;
}
//查找右边等于val的元素
while(left<=right&&nums[right]==val) //left=2 < right =3 nums[3]=val ----- right = 2
{
--right;
}
// 将右边不等于val的元素覆盖左边等于val的元素
if(left<right) //left=1 < right=2
{
nums[left++]=nums[right--];
}
}
return left;
}
};