目录
704 二分查找
二分查找
重点把握范围右边是闭的还是开的
由此引申出有两种写法
左闭右闭写法
因为右边是闭的,因此,最右边的那个值是可以取到的,因此while里面才加上“ = ”。
同理如果中间值大于目标值时,右边界重取,需要 -1,因为我们已经取过了。
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0, right = nums.size() - 1;//确定两边边界
int middle = (left + right) / 2;
//左闭右闭
while(left <= right){//如果左边的值大于右边就越界了,说明不存在返回-1
if(nums[middle] < target){//小于目标值,说明在右半边
left = middle + 1;//重新确定左边界,中间的那个值比过了+1跳过
middle = (left + right) / 2;
}else if(nums[middle] > target){//大于目标值,说明在右半边
right = middle - 1;//因为右闭,而我们已经把这个中间值比较过了,所以-1跳过
middle = (left + right) / 2;
}else if(nums[middle] == target){//找到了,返回下标值
return middle;
}
}
return -1;
}
};
左闭右开写法
因为右边是开的取不到,所以while里面不可以取“ = ”。
并且在下面右边界的重新选取不需要 -1,因为是取不到的,如果-1就少了一个值。
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0, right = nums.size();//确定两边边界
int middle = (left + right) / 2;
//左闭右开
while(left < right){//如果左边的值大于等于右边就越界了,说明不存在返回-1
if(nums[middle] < target){//小于目标值,说明在右半边
left = middle + 1;//重新确定边界,左值等于中间值
middle = (left + right) / 2;
}else if(nums[middle] > target){//大于目标值,说明在右半边
right = middle;
middle = (left + right) / 2;
}else if(nums[middle] == target){//找到了,返回下标值
return middle;
}
}
return -1;
}
};
27 移除元素
主要思路采取双指针的方法
双指针:分为一个慢指针,一个快指针,快指针顾名思义走的快负责把整个数组完全遍历一遍并且判断走过的这些数满不满足规则,慢指针的作用是来响应那些满足的数,不用完全遍历那些数。
比如上面的去除指定元素,快指针先遍历,每进一步就判断数组里面的数等不等于 val,等于快指针直接++跳过这个数,不等于说明不是需要去除的数,就让慢指针对应的数组值等于快指针的值,然后慢指针++。
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int slow = 0;//慢指针
int fast = 0;//快指针
if(nums.size() == 0){//需要判断一下数组为不为空
return 0;
}
for(int i = 0; i < nums.size(); i++){
if(nums[fast] != val){//如果找到了不等于的就可以直接赋值给慢指针
nums[slow++] = nums[fast++];
}else{
fast++;//说明等于要删除的值,++跳过,不让慢指针读到
}
}
return slow;//返回数组长度
}
};
如果用快指针来代替 i 放在 for 循环里面就不用在外面判断数组为不为空了