JS有序数组的平方

179 阅读3分钟

✈题目

力扣题目链接

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

🚠思路

暴力的解决办法先平方再排序,时间复杂度是O(nlogn),空间复杂度是空O(logn)。

另一个思路:数组中的元素经过平方后,其最大值要么出现在原数组的起始位置,要么出现在末尾位置,因为负数的平方会变得很大,可能超过正数。

所以,为了找到平方后的最大值,我们可以使用双指针方法:i从数组的开头开始,j从数组的末尾开始,然后比较两个指针所指向元素的平方值,将较大的那个放入新数组的末尾,并移动相应的指针。这样,我们就能在新数组的末尾位置依次找到平方后的最大值、次大值等。

如果 A[i] * A[i] < A[j] * A[j] 那么 result[k--] = A[j] * A[j];

如果 A[i] * A[i] >= A[j] * A[j] 那么 result[k--] = A[i] * A[i];

🛰暴力拆解

对一个数组nums进行for循环,将所有元素平方,然后将平方后的数组按升序排序,最后返回这个排序后的数组。

/**
 * 将给定数组中的每个元素平方后,对结果进行排序并返回。
 *
 * @param nums 给定的整数数组
 * @returns 排序后的平方数数组
 */
function sortedSquares(nums) {
  for (let i = 0; i < nums.length; i++) {
    nums[i] *= nums[i];
  }

  nums.sort((a, b) => a - b);
  return nums;
}
const arr = [-4, -1, 0, 3, 10];
console.log(sortedSquares(arr));

或者使用for..of更加简洁

function sortedSquares(nums) {
  let arr = [];
  for (let num of nums) {
    arr.push(num * num);
  }
  return arr.sort((a, b) => a - b);
}

注意

如果这里的sort()不写参数的话,会默认会将元素转换为字符串并按 Unicode 码点顺序排序,而非按数值大小排,输出结果为[ 0, 1, 100, 16, 9 ],先比较第一位数字,再比较第二位数字。若需按数值从小到大排序,需传入比较函数

🚀双指针

此时的时间复杂度为O(n) 空间复杂度:O(1),相对于暴力解决的解法O(nlog n)还是提升不少的。

function sortedSquares(nums) {
  let i = 0;
  let j = nums.length - 1;
  let k = nums.length - 1;
  let arr = [];
  while (i <= j) {
    let left = nums[i] * nums[i];
    let right = nums[j] * nums[j];
    if (left < right) {
      arr[k--] = right;
      j--;
    } else {
      arr[k--] = left;
      i++;
    }
  }
  return arr;
}

🚁总结

这题要求将给定非递减顺序数组的每个数字平方后,再按非递减顺序排序。一开始我们会想到采用暴力解法先平方后排序,但更优解为使用双指针法,从数组两端向中间遍历,比较平方值后逆序放入新数组,时间复杂度为O(n),空间复杂度为O(1)。

📖参考笔记:代码随想录