算法训练营1.14(1)
训练营第一天:704二分查找 27 移除元素 977 有序数组的平方
704.二分查找
记录:
使用二分法的前提条件:有序数组 、无重复元素
主要问题:到底是 while(left < right) 还是 while(left <= right),到底是right = middle呢,还是要right = middle - 1呢?
区分方法:1.区间是否合法?2.思考下一次更新是否包含该边界?
实操出现的问题:
1.循环条件:while(left < right)或者while(left <= right),而不是while(left != right) 为什么?
2.区间的左闭右闭和左闭右开:一方面会导致循环条件和下一次更新区间的不同,另一方面会影响 right的起始值,如果是左闭右闭, right=nums.size()-1,因为闭区间是包含这个数的,左闭右开 right=nums.size(),因为不包含该数。
第一种写法:区间左闭右闭
// 版本一
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0;
int right = nums.size() - 1; // 定义target在左闭右闭的区间里,[left, right]
while (left <= right) { // 当left==right,区间[left, right]依然有效,所以用 <=
int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2
if (nums[middle] > target) {
right = middle - 1; // target 在左区间,所以[left, middle - 1]
} else if (nums[middle] < target) {
left = middle + 1; // target 在右区间,所以[middle + 1, right]
} else { // nums[middle] == target
return middle; // 数组中找到目标值,直接返回下标
}
}
// 未找到目标值
return -1;
}
};
和自己代码的不同:防止溢出
第二种写法:区间左闭右开
// 版本二
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0;
int right = nums.size(); // 定义target在左闭右开的区间里,即:[left, right)
while (left < right) { // 因为left == right的时候,在[left, right)是无效的空间,所以使用 <
int middle = left + ((right - left) >> 1);
if (nums[middle] > target) {
right = middle; // target 在左区间,在[left, middle)中
} else if (nums[middle] < target) {
left = middle + 1; // target 在右区间,在[middle + 1, right)中
} else { // nums[middle] == target
return middle; // 数组中找到目标值,直接返回下标
}
}
// 未找到目标值
return -1;
}
};
27.溢移除元素
数组中移除元素并不容易! | LeetCode:27. 移除元素_哔哩哔哩_bilibili
记录:
数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖
双指针解法:慢指针代表的是新数组,快指针用来遍历整个数组。
实操出现的问题:
返回值slow而不是slow+1,因为在最后slow进行了自增的操作。
代码:
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int slow=0;
int fast=0;
for(;fast<nums.size();fast++)//fast指针遍历数组
{
if(nums[fast]!=val)//只有当fast指向的数和目标数不等的时候进行替换,因为目标数组想要的就是非目标数
{
nums[slow++]=nums[fast];
}
}
return slow;
}
};
977.有序数组的平方
双指针法经典题目 | LeetCode:977.有序数组的平方_哔哩哔哩_bilibili
记录:
双指针指向首尾(绝对值最大的元素一定在首尾),逐个比较,大数放在新数组的最末尾,直至遍历完成整个数组
循环条件:while(fast>=slow):为什么有等于?如果没有等于,相当于对最后一个元素不进行操作。
实操出现的问题:
1.初始化数组vector<int> result(nums.size())
2.fast slow都是数组索引
代码对比:
我自己的:
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int fast=nums.size()-1;
int index=nums.size()-1;//result数组的索引,从最末尾开始
int slow=0;
vector<int> result(nums.size());// 初始化结果数组
while(fast>=slow)
{
if(nums[fast]*nums[fast]<nums[slow]*nums[slow])
{
result[index--]=nums[slow]*nums[slow];
slow++;
}
else
{
result[index--]=nums[fast]*nums[fast];
fast--;
}
}
return result;
}
};

浙公网安备 33010602011771号