代码随想录-数组-有序数组的平方

46 阅读2分钟

给你一个按 非递减顺序 排序的整数数组 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]

思路

暴力解法

先for循环遍历获取当前数组元素的平方,组成一个新数组,然后将新数组中元素重新进行排序后返回数组。

function sort(nums: Array<number>): number[] {

  // 声明一个空数组用于存储数组元素平方后的排序

  let arr: number[] = []

  // 先遍历数组,获取数组元素的平方

  for (let i = 0; i < nums.length; i++) {

    arr.push(nums[i] * nums[i])

  }

  // 再将数组元素的平方进行排序

  arr.sort((a, b) => a - b)

  // 返回排序后的数组

  return arr

}

复杂度分析

时间复杂度:O(nlogn),其中 n 是数组 nums 的长度。

空间复杂度:O(logn)。除了存储答案的数组以外,我们需要 O(logn) 的栈空间进行排序。

双指针法

已知数组是有序排列的整数数组,但是数组元素可能为负数,所以数组元素的平方可能不是按顺序排列的,但是我们可以知道数组元素平方后的最大值一定在数组的最左侧或最右侧(绝对值大的一侧)。

可以使用双指针法,分别使用i和j指针指向数组的起始位置和结束位置,比较这两个位置元素平方的大小,取较大者,指针可以向中间移动,按从大到小的顺序依次从后往前放入新数组中

977.有序数组的平方.gif

function sort0(nums: number[]): number[] {

  let len: number = nums.length

  // 创建数组存储数组元素平方排序后的元素

  let arr: number[] = new Array(len).fill(0)

  // 左侧指针

  let i: number = 0

  // 右侧指针

  let j: number = len - 1

  // 新数组中正在排序的元素的下标

  let k: number = len - 1

  while (i <= j) {

    let left = nums[i] * nums[i]

    let right = nums[j] * nums[j]

    // 比较左侧指针和右侧指针所指向的元素的平方的大小

    if (left >= right) {

      // 较大者加入数组,然后指针向中间移动

      arr[k] = left

      i++

    } else {

      arr[k] = right

      j--

    }

    k--

  }

  // 返回排序后的新数组

  return arr

}

复杂度分析

时间复杂度:O(n),其中 n 是数组 nums 的长度。

空间复杂度:O(1)。除了存储答案的数组以外,我们只需要维护常量空间。