LeetCode —— 977. 有序数组的平方

98 阅读2分钟

启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第9天,点击查看活动详情

该题是数组二分查找题型第五题。

题目来源

977. 有序数组的平方 - 力扣(LeetCode)

题目描述(简单

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

题目解析

直接排序

最简单的方法就是将数组元素平方后得到新数组,进行排序后返回最终数组。

代码

/**
 * @param {number[]} nums
 * @return {number[]}
 */
var sortedSquares = function(nums) {
    nums = nums.map((item) => {
        return item * item
    })
    return nums.sort(function(left, right) {return left -right})
};

如图:

image.png

双指针

在直接排序中,我们没有用到原数组为升序数组这个条件。如果数组 nums 中的所有数都是非负数,那么将每个数平方后,数组仍然保持升序;如果数组中所有数都是负数,那么将每个数平方后,数组将为降序。

假设 num 为数组 nums 中负数和非负数的分界线。那么 nums[0]nums[num] 均为负数, nums[num + 1]nums[nums.length - 1] 均为非负数。当数组的元素平方后,那么 nums[0]nums[num] 单调递减, nums[num + 1]nums[nums.length - 1] 单调递增。此时以 num 为分界线,出现两个有序的区间,最后采用 归并排序 的方法即可。

代码

先找到原数组的最后一个负数的下标,在由左右指针依次遍历平方后的数组判断大小,将小的平方值放入新数组。

/**
 * @param {number[]} nums
 * @return {number[]}
 */
var sortedSquares = function(nums) {
    let left = 0, right = 0, res = [], length = nums.length
    nums = nums.map((item, index) => {
        if (item < 0) {
            left = index
        }
        return item * item
    })
    right = left + 1
    while (left >= 0 || right < length) {
        if (left < 0) {
            res.push(nums[right])
            right++
        }else if (right === length) {
            res.push(nums[left])
            left--
        }else if (nums[left] < nums[right]) {
            res.push(nums[left])
            left--
        }else{
            res.push(nums[right])
            right++
        }
    }
    return res
};

image.png

执行用时和内存消耗仅供参考,大家可以多提交几次。如有更好的想法,欢迎大家提出。