力扣数组

977. 有序数组的平方

977. 有序数组的平方

https://leetcode.cn/problems/squares-of-a-sorted-array

题目

给你一个按 非递减顺序 排序的整数数组 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 <= 10⁴
  • -10⁴ <= nums[i] <= 10⁴
  • nums 已按 非递减顺序 排序

思路

核心逻辑:利用原数组「非递减」的特性,平方后的最大值必然出现在数组两端(负数绝对值越大平方越大,正数越大平方越大)。通过三个指针实现高效填充:

  1. 左指针 left 指向数组头部,右指针 right 指向数组尾部,分别代表当前待比较的两端元素;
  2. 结果指针 i 指向结果数组的尾部,代表当前需要填充的位置;
  3. 比较 leftright 对应元素的平方值,将较大值放入 res[i],并移动对应指针(left 右移 / right 左移),同时 i 左移;
  4. 循环直到 left > right(所有元素处理完毕),结果数组即为非递减的平方数组。

解法

nums = [-4,-1,0,3,10]

def sortedSquares(nums: list[int]) -> list[int]:
    n = len(nums)
    left, right, i = 0, n - 1, n - 1
    res = [0] * n
    
    while left <= right:        
        left_sq = nums[left] ** 2
        right_sq = nums[right] ** 2
        if left_sq > right_sq:
            res[i] = left_sq
            left += 1
        else:
            res[i] = right_sq
            right -= 1
        i -= 1
    return res

print(sortedSquares(nums))  # 输出:[0,1,9,16,100]

解释

代码片段作用与原因
left, right, i = 0, n - 1, n - 1初始化指针:left/right 覆盖原数组两端,i 从结果数组尾部开始填充(先放最大值)
res = [0] * n预先初始化固定长度的结果数组,避免动态扩容,空间复杂度 O(n)
while left <= right循环条件:只要左右指针未交叉,说明还有元素未处理(left==right 时处理最后一个元素)
left_sq = nums[left] ** 2 / right_sq = nums[right] ** 2计算两端元素平方,避免重复计算,命名更语义化
res[i] = left_sq + left += 1左指针元素平方更大,将其放入当前结果位置,左指针右移缩小范围
res[i] = right_sq + right -= 1右指针元素平方更大/相等,将其放入当前结果位置,右指针左移缩小范围
i -= 1结果指针左移,准备接收下一个次大值,保证结果数组非递减