目录
704-二分查找
输入:nums = [-1, 0, 3, 5, 9, 12]
target = 9
输出:4
解释:9出现在nums中,下标为4
二分查找右两种写法:左闭右闭和左闭右开
左闭右闭
左闭:int left = 0; //下标为0,可以取到
右闭:int right = nums.size() - 1; //最后一个下标,可以取到
while的判断条件要写成“left <= right”, 而不是“left < right”! 因为left是有可能==right,且还需要再次进入while循环中进行比较;
right=mid - 1而不是right = mid;
输入:[-1, 0, 3, 5, 9, 11] targrt = 11
第一次:mid = (0 + 5) / 2 = 2 -> 3 //下标2指向3
3 < 11 则: left = mid + 1 = 2 + 1 = 3 ->5 //下标3指向5
mid = (3 + 5) / 2 = 4 -> 9
9 < 11 则: left = mid + 1 = 4 + 1 = 5 == right ->11 //此时left == right ->11
mid = (5 + 5) / 2 //如果写成left < right,不会进行到这一步,最后的right没有遍历到,导致返回未找到target;
11 == 11 则返回mid
提交代码-704二分查找-左闭右闭
//左闭右开
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0;
int right = nums.size() - 1; //左闭右闭
int mid = (left + right) / 2;
while(left <= right){ //左闭右闭,要left<=right
mid = (left + right) / 2;
if(nums[mid] == target){
return mid;
}
else if(nums[mid] < target){
left = mid + 1;
}
else{
right = mid - 1;
}
}
return -1;
}
};
左闭右开
左闭:int left = 0; //下标为0,可以取到
右开:int right = nums.size() ; //最后一个下标,取不到
while的判断条件要写成“left < right”! 因为right的值是非法越界的(第一次)或者已经遍历过的不符合条件的数值(nums[right] > target),不需要再次进入while循环中进行比较;
right=mid!
输入:[-1, 0, 3, 5, 9, 11] targrt = 2
第一次:mid = (0 + 5) / 2 = 2 -> 3 //下标2指向3
3 > 2 则: right = mid = 2 -> 3 //下标2指向3,此时的right已经作为上一次的mid被遍历过了,不符合target的值,是无效值;
提交代码-704二分查找-左闭右开
//704
//左闭右开
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){ //左闭右开,left == right无意义
mid = left + (right - left) / 2; //防止越界
if(nums[mid] == target){
return mid;
}
else if(nums[mid] < target){
left = mid + 1;
}
else{
right = mid; //左闭右开,mid 作为下一个right,代表不会取到这个下标
}
}
return -1;
}
};
27-移除元素
输入:nums = [0,1,2,2,3,0,4,2], val = 2 输出:5, nums = [0,1,3,0,4] 解释:函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4 。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素。
双指针
思路:
1、左指针->第一位, 右指针指向最后一位;
2、左指针从前往后遍历,将==val的值和右指针的值交换; //左指针前面的数都是!=val的,右指针后面的都是==val的,需要删除
3、删除右指针指向的交换后的==val的元素,右指针前移;
提交代码-27移除元素
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int left = 0;
int right = nums.size() - 1; //双指针
while(left <= right){
if(nums[left] == val && nums[right] != val){ //左边==val,右边不等,左右交换,左后移,右删除,右前移
nums[left] = nums[right];
nums[right] = val;
nums.erase(nums.begin() + right);
left++;
right--;
}
else if(nums[left] == val && nums[right] == val){ //左==val,右也等于val,左不动,右删除,右前移
nums.erase(nums.begin() + right);
right--;
}
else{ //左边!=val,左后移
left++;
}
}
return nums.size(); //返回剩余数组大小
}
};