977.有序数组的平方和


在这里插入图片描述


需求

给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。

示例 1:
输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]

示例 2:
输入:nums = [-7,-3,2,3,11]
输出:[4,9,9,49,121]

提示:
1 <= nums.length <= 104
-104 <= nums[i] <= 104
nums 已按 非递减顺序 排序

进阶:
请你设计时间复杂度为 O(n) 的算法解决本问题

该题目在力扣的链接


版本1

通过对需求的分析, 先写出第一个版本:

public int[] sortedSquares(int[] nums) {
    int length = nums.length;
    int[] resultArr = new int[length];
    int left = 0;
    int right = length - 1;
    int index = right;
    while( left <= right ){
       resultArr[index--] = nums[left] * nums[left] > nums[right] * nums[right] 
       	?  nums[left] * nums[left++] : nums[right] * nums[right--];
    }
    return resultArr;
}

版本1使用了双指针技术来解决问题。left 指针指向数组的起始位置,而 right 指针指向数组的末尾。index 变量则用于跟踪结果数组中最后一个元素的索引。

在 while 循环中,代码比较 left 和 right 指针所指向的数的平方值,将较大的平方值放入结果数组的 index 位置,并更新相应的指针。

如果 nums[left] 的平方大于 nums[right] 的平方,则将 nums[left] 的平方放入结果数组,并将 left 指针向右移动一位;否则,将nums[right] 的平方放入结果数组,并将 right 指针向左移动一位。每次放入平方值后,index 都会递减,直到 left 和 right 指针相遇,循环结束。

这种方法的时间复杂度为O(n),因为它只需要遍历一次原数组。

执行结果很丝滑:

在这里插入图片描述


版本2

版本1中的代码 :

resultArr[index--] = nums[left] * nums[left] > nums[right] * nums[right] 
       	?  nums[left] * nums[left++] : nums[right] * nums[right--];

我们可以看到 nums[left] * nums[left] 这个表达式执行了两次, 其实执行一次就行了, 只不过我们要用变量将其保存起来.

可以修改为如下代码:

public int[] sortedSquares(int[] nums) {
    int length = nums.length;
    int[] resultArr = new int[length];
    int left = 0;
    int right = length - 1;
    int index = right;
    int leftValue;
    int rightValue;
    while( left <= right ){
        leftValue = nums[left] * nums[left];
        rightValue = nums[right] * nums[right];
        if( leftValue > rightValue ){
            resultArr[index--] = leftValue;
            left++;
        } else{
            resultArr[index--] = rightValue;
            right--;
        } 
    }
    return resultArr;
}

执行结果依然很丝滑. 就是内存加了点.

在这里插入图片描述


注意要点

循环结束条件

在该算法下, 我们的循环结束条件定为了 left <= right, 这是因为, 我们的双指针分别从左边和最右边向中间靠拢, 而且每次只有一个指针在移动, 并不是一起移动的. 当两个指针重合的时候, 也就是数组的所有数据都遍历比较完成了.

为什么index从数组末尾开始

这是因为需求里是要的平方和, 并且是按照非递减的顺序排列, 而给出的原数组中是存在 负数 的.
所以当我们的两个指针分别从数组起始值和结尾位置比较的时候, 可以找到最大值, 但是不一定能找到最小值. 比如 数组: { -4, 1, 3, 6, 9}; 当我们的两个指针开始比较时候, -4 和 9 分别平方后可以找到最大值, 但是不能找到最小值. 因为 1 平方后会比 -4 平方 要小.


结尾

以上 是我对有序数组平方和的一些遐想和延伸, 可能不是最优解, 但是算法的优化嘛 本身就是一个思索的过程, 能在这个思索和迭代的过程中有所收获和乐趣就是在成长了, 欢迎大家一起来交流更多的解答…





  • 14
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值