977. 有序数组的平方

977. 有序数组的平方

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        // for(int i =0;i<nums.size();i++){
        //     nums[i]= pow(nums[i],2);
        // }
        // sort(nums.begin(),nums.end());
        // return nums;
        int left = 0;
        int  right = nums.size()-1;
        vector<int> res(nums.size());
        int index = right;
        while(left<=right){
            if(nums[left]*nums[left] >= nums[right]*nums[right] ){
                res[index--] = nums[left]*nums[left];
                left++;
            }
            else{
                res[index--] = nums[right]*nums[right];
                right --;
            }
        }
        return res;
    }

};

好的,我会详细解释这段代码的逻辑,它使用了 双指针法 来实现原地修改数组,移除所有值等于 val 的元素。下面我们逐步分析每一行代码的作用:

代码:

for (int i = 0; i < nums.size(); i++) {
    if (nums[i] != val) {
        nums[k] = nums[i];  // 将不等于 val 的元素移到前面
        k++;  // 更新下一个可以存放不等于 val 的位置
    }
}

1. 外部循环:for (int i = 0; i < nums.size(); i++)

  • 这里使用了一个 for 循环来遍历数组 nums 中的每个元素。i 是当前遍历到的元素的索引。
  • i0 开始,直到 nums.size()(数组的大小),也就是遍历整个数组。

2. 检查当前元素是否等于 valif (nums[i] != val)

  • 在每次遍历中,判断当前元素 nums[i] 是否不等于 val
  • 如果 nums[i] != val,说明该元素应该保留在数组中。也就是说,这个元素不等于要移除的元素,我们希望它继续存在并移到数组的前面。
  • 如果 nums[i] == val,则跳过当前元素,不做任何操作,因为题目要求删除所有等于 val 的元素。

3. 将符合条件的元素放到数组前面:nums[k] = nums[i];

  • 当当前元素 nums[i] 不等于 val 时,将它放到 nums[k] 位置。
  • 这里的关键在于 k 的作用,k 是指向数组中下一个可以放置有效元素的位置。也就是说,k 标记着数组中不等于 val 的元素的个数,同时也指向下一个可以存放不等于 val 元素的位置。
  • 这样,所有不等于 val 的元素都会依次被放到数组的前 k 个位置。

4. 更新 k 的值:k++;

  • k 每次加 1,意味着下一个符合条件的元素应该存放在 nums[k] 的位置。
  • 这样,k 会随着遍历逐渐增长,最终它的值表示数组中不等于 val 的元素的数量。

整体流程:

  1. 初始化

    • 假设数组 nums = {3, 2, 2, 3, 4, 5}val = 3
    • 初始化 k = 0,表示可以放置第一个不等于 val 的元素的位置。
  2. 遍历数组

    • 第一次遍历:i = 0nums[0] = 3,它等于 val,所以跳过。
    • 第二次遍历:i = 1nums[1] = 2,它不等于 val,所以将 nums[1] 移到 nums[0] 位置,nums 变成 {2, 2, 2, 3, 4, 5},同时更新 k = 1
    • 第三次遍历:i = 2nums[2] = 2,它不等于 val,所以将 nums[2] 移到 nums[1] 位置,nums 变成 {2, 2, 2, 3, 4, 5},同时更新 k = 2
    • 第四次遍历:i = 3nums[3] = 3,它等于 val,所以跳过。
    • 第五次遍历:i = 4nums[4] = 4,它不等于 val,所以将 nums[4] 移到 nums[2] 位置,nums 变成 {2, 2, 4, 3, 4, 5},同时更新 k = 3
    • 第六次遍历:i = 5nums[5] = 5,它不等于 val,所以将 nums[5] 移到 nums[3] 位置,nums 变成 {2, 2, 4, 5, 4, 5},同时更新 k = 4
  3. 结束遍历

    • 最终,数组的前 k 个位置保存了所有不等于 val 的元素:nums = {2, 2, 4, 5, _, _},其中 _ 表示数组后面的部分不重要。
    • 返回 k = 4,即不等于 val 的元素数量。

结果:

最终,数组 nums 被修改为 nums = {2, 2, 4, 5, _, _},返回 4

总结:

  • k 记录数组中不等于 val 的元素数量。
  • k 同时也指向下一个可以放置不等于 val 元素的位置。
  • 通过 nums[k] = nums[i],我们将所有不等于 val 的元素移到数组的前面,最终返回 k,表示有效元素的数量。
  • 这种方式是 原地 修改数组,空间复杂度是 O(1),且时间复杂度是 O(n),因为只需要一次遍历。

这种做法既高效又符合题目要求,不需要额外的空间来存储结果。

是的,result[index--] = leftSquare; 这一行的作用可以分解成以下两步:

  1. result[index] = leftSquare;
    • 这里把 leftSquare 赋值给 result[index],即将 leftSquare(当前左指针位置的平方值)存储到 result 数组的当前位置。
  2. index--
    • index-- 是自减操作,意味着在赋值之后,index 的值会减 1。这样,下一次存值时,index 会指向 result 数组的前一个位置,从而实现从数组的尾部向前填充结果数组。

为什么这么做?

我们使用了 双指针法 从两端开始比较平方值,然后按降序的顺序(较大的平方值先放入结果数组)填充 result 数组。由于是从尾部开始填充,最终 result 数组会按照升序排列。

举个例子:

假设输入数组为 nums = [-4, -1, 0, 3, 10],目标是返回它们的平方并按升序排序。

初始状态:
nums = [-4, -1, 0, 3, 10]
left = 0   // 指向 -4
right = 4  // 指向 10
result = [0, 0, 0, 0, 0]  // 初始结果数组,全为0
index = 4  // 从结果数组的最后一个位置开始
第一步:
  • leftSquare = (-4) * (-4) = 16
  • rightSquare = 10 * 10 = 100
  • 由于 rightSquare 更大,将 100 放入 result[index],即 result[4] = 100,然后 index-- 变为 3right-- 变为 3
第二步:
  • leftSquare = (-4) * (-4) = 16
  • rightSquare = 3 * 3 = 9
  • leftSquare 更大,将 16 放入 result[index],即 result[3] = 16,然后 index-- 变为 2left++ 变为 1
第三步:
  • leftSquare = (-1) * (-1) = 1
  • rightSquare = 3 * 3 = 9
  • rightSquare 更大,将 9 放入 result[index],即 result[2] = 9,然后 index-- 变为 1right-- 变为 2
第四步:
  • leftSquare = (-1) * (-1) = 1
  • rightSquare = 0 * 0 = 0
  • leftSquare 更大,将 1 放入 result[index],即 result[1] = 1,然后 index-- 变为 0left++ 变为 2
第五步:
  • leftSquare = 0 * 0 = 0
  • rightSquare = 0 * 0 = 0
  • 0 放入 result[index],即 result[0] = 0,然后 index-- 变为 -1,循环结束。
最终结果:
result = [0, 1, 9, 16, 100]

总结:

  • result[index--] = leftSquare; 是一个复合操作,先将 leftSquare 存入 result[index],然后将 index 减 1,使得下一次可以将值存入 result 数组的前一个位置。
  • 这样做的目的是 从结果数组的后端向前填充,确保我们按照降序选择平方数填充,最终数组是升序的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值