977. 有序数组的平方
题目详细:LeetCode.977
解这道题的思路和方法有很多,最简单的方法就是计算出数组中每个元素的平方数,并记录在新数组中,最后对新数组进行排序即可得到答案,但这个方法效率不高,所以在这里我们讨论一种时间复杂度为 O(n) 的算法来解决本问题。
首先,由题意可知:
- 输入的整数数组 nums 是
非递减顺序
排序的(即有序的、递增的) - 返回
每个数字的平方
组成的新数组- 负数的平方数为正数
- 正数的平方数为正数
通过以上的信息易知,假如我们按从小到大的顺序,依次计算每个数组元素的平方数后,是无法保证新数组依旧是有序的,且此做法并没有利用到数组nums是有序的这一特点。
那么如何去利用nums数组是有序的这一特点呢?
当我们按顺序计算数组中每个元素的平方数后,根据nums数组有序的特点可以发现,其新数组的元素分布有两边大中间小/依旧有序
的特点,根据这一特点我们可以设计一个辅助数组和两个指针(双指针):
- 定义一个与原数组相同大小的辅助数组,并定义一个指针指向数组的尾部(指向尾部保证结果递增,指向头部则保证结果递减)
- 定义一个左指针从小端开始,依次计算每个元素的平方数
- 定义一个右指针从大端开始,依次计算每个元素的平方数
- 比较左右两个指针得到的平方数大小,为了保证新数组是非递减顺序排序的
- 将较大的平方数赋给辅助数组当前指针指向的位置,并移动已赋值的指针像另一端前进
- 在每一次比较后,都能够保证辅助数组是递增的,辅助数组的指针左移一位
- 直到左右两个指针相遇,表示原数组遍历完毕,结束循环
- 最终得到的辅助数组作为结果返回,时间复杂度 O(n)
Java解法(辅助数组 + 双指针):
class Solution {
public int pow(int n){
return n*n;
}
public int[] sortedSquares(int[] nums) {
int n = nums.length, l = 0, r = n-1;
// 定义一个与原数组相同大小的辅助数组
int[] res = new int[n];
// 定义一个指针指向数组的尾部(指向尾部保证结果递增,指向头部则保证结果递减)
int p = n - 1;
while(l <= r){
int l_val = pow(nums[l]);
int r_val = pow(<