2024年10月8日
参考github网站:代码随想录
1.二分查找
cpp
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0;
int right = nums.size()-1;
while(left<=right){
int middle = (left+right)/2;
if(nums[middle] > target){
right = middle -1;
}
else if(nums[middle] < target){
left = middle +1;
}
else return middle;
}
return -1;
}
};
核心是边界处理。
以左右均为闭区间为例:
第一个点是while循环中left是可以等于right的,因为[1,1]仍然有意义,否则就是丢情况;
第二个点是在进行左右两个区间分割的时候,是将middle-1传递给right或middle+1传递给left,如果将middle传递,是因为区间是闭区间,middle是被包含的,但是middle一定不是target的目标值(nums[middle] > target)。相反在左闭右开区间,开区间的部分就是传递middle了。
2.移除数组元素(快慢指针)
在牛客上遇见过,当时用的暴力求解:
cpp
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 + 1; j < size; j++) {
nums[j - 1] = nums[j];
}
i--;
size--;
}
}
return size;
}
};
思路上就是外层循环遍历每个元素,找到目标元素后内层循环依次向前替换位置。
但是这里有个问题:for (int j = i + 1;...),如果是j=i,那么后面nums存在j+1造成数组超限。
快慢指针的方法:
两个指针一个fast,一个slow,分别有自己的职责。
快指针查找目标值(找寻新数组元素),慢指针查找指向更新的位置。
cpp
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int size = nums.size();
int slow = 0;
for(int fast = 0; fast < size; fast++){
if(val != nums[fast]){
nums[slow++] = nums[fast];
}
}
return slow;
}
};
快指针在for循环中不停下,一直走到头;慢指针当快指针找到目标元素的时候停下不动,确定好交换的初始位置(尤其是遇到连续两个目标元素的时候!!)。