704.二分查找
使用二分法的前提条件:
1.数组为有序数组
2.数组中无重复元素
思路:
1、双指针法,一前一后,对半查找
2、确定区间不变,[ ] or [ )
3、是个重复的过程,用while循环,确定循环条件
易错点:
1.while循环的条件 left <= right or left < right
2.right = middle - 1 or right = middle
3.采用[left, right) 时还需要注意right的初始值为right = nums.size();(因为区间不包含右边界
区间的一般定义为:
1.[left, right]
2.[left, right) 此处的区间就是我们每次循环的搜索区间
**原则:**选定区间并坚持这个定义!
注意: int middle = (left + right)/2 两个int型相加有时候会越界,可用int middle = left + (right - left)/2 代替。
使用左闭右闭区间的代码如下:
class Solution {
public:
int search(vector<int>& nums, int target) {
/*
1、双指针法,一前一后,对半查找
2、确定区间不变,[ ]
3、是个重复的过程,用while循环,确定循环条件
*/
int left = 0;
int right = nums.size() - 1;
while(left <= right){
int middle = left + (right - left) / 2;
if(nums[middle] < target){
left = middle + 1;
}else if(nums[middle] > target){
right = middle - 1;
}else{
return middle;
}
}
return -1;
}
};
使用左闭右开区间的代码如下:
class Solution {
public:
int search(vector<int>& nums, int target) {
/*
1、双指针法,一前一后,对半查找
2、确定区间不变,[ )
3、是个重复的过程,用while循环,确定循环条件
*/
int left = 0;
int right = nums.size();
while(left < right){
int middle = left + (right - left) / 2;
if(nums[middle] < target){
left = middle + 1;
}else if(nums[middle] > target){
right = middle;
}else{
return middle;
}
}
return -1;
}
};
27.移除元素
解法一: 暴力解法,双层for循环
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
/*
1、暴力解法,双层for循环
2、一层for循环找val,另一层更新数组
*/
int size = nums.size();
for(int i = 0; i < size; i++){
if(nums[i] == val){
for(int j = i + 1; j < size; j++){
nums[j - 1] = nums[j];
}
size--;
i--;
}
}
return size;
}
};
自己写的时候出现的问题:
1、循环条件写成 i < nums.size()
和 j < nums.size()
。显然是错误的。若满足条件nums[i] == val
,则通过内层for循环后,数组后面的元素都会往前进行覆盖,那么数组在nums.size()这个位置就没了意义,于是就会出现问题。错误为:超出时间限制。
2、内层循环写成
for(int j = i; j < size; j++){
nums[j] = nums[j + 1];
}
一开始觉得和正确的代码没什么区别,其实不然。此处问题在于,当写成 nums[j] = nums[j + 1]
时,若 j
到达数组最后一位时,并没有 nums[j+1]
可用于赋值,已经超出数组的范围了。错误为:ERROR: AddressSanitizer: heap-buffer-overflow on address。
3、把size--
写进了内层for循环里。显然错误。
4、漏掉了i--
。每次往前覆盖时,i
就应该从原地开始执行if
判断。
解法二: 双指针解法
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
/*
1、双指针解法,快慢指针追逐
*/
int slow = 0;
for(int fast = 0; fast < nums.size(); fast++){
if(nums[fast] != val){
nums[slow] = nums[fast];
slow++;
}
}
return slow;
}
};
总结:
记录还是蛮费时间的,而且这两题还是之前都做过了的。不过,自己亲手敲一遍真的能发现很多错误。继续加油。