算法训练营1.14(1)

训练营第一天:704二分查找 27 移除元素 977 有序数组的平方

704.二分查找

视频讲解

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

27. 移除元素 | 代码随想录

记录:

数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖

双指针解法:慢指针代表的是新数组,快指针用来遍历整个数组。

实操出现的问题:

返回值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.有序数组的平方

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;
    }
};
posted @ 2026-01-14 11:36  欧尼酱ovo  阅读(10)  评论(0)    收藏  举报