LeetCode:977 有序数组的平方

113 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第18天,点击查看活动详情

题目

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

进阶:

  • 请你设计时间复杂度为 O(n) 的算法解决本问题

解题

解题一:双指针

思路

  1. 定义小于零的指针(minstart),从下标 0 开始,向左比较并移动,并且找到最大小于零的位置
    • 注意:最大不能超过数组长度
  2. 定义 maxstart 指针(minstart 后一位)开始
  3. maxstart 向右,minstart 向左,计算两个数组的平方,比较大小,然后存入 result 数组中
  4. 以此类推,直到将大于零或小于零的部分完全加入数组
  5. 将剩余的数字按照平方和的结果插入 result 数组中

代码

class Solution {
    public int[] sortedSquares(int[] nums) {
        int[] result = new int[nums.length];
        if(nums.length==0){
            return result;
        }
        int minstart = 0;
        while (minstart< nums.length-1 && nums[minstart+1] < 0) {
            minstart++;
        }
        // temp >= 0
        int maxstart = minstart+1;
        int index = 0;
        while (minstart >= 0 && maxstart < nums.length) {
            if (Math.abs(nums[minstart]) <= nums[maxstart]) {
                result[index++] = nums[minstart] * nums[minstart--];
            } else {
                result[index++] = nums[maxstart] * nums[maxstart++];
            }
        }
        while (minstart >= 0) {
            result[index++] = nums[minstart] * nums[minstart--];
        }
        while (maxstart < nums.length) {
            result[index++] = nums[maxstart] * nums[maxstart++];
        }
        return result;
    }
}

总结

性能分析

  • 执行耗时:1 ms,击败了 100.00% 的 Java 用户
  • 内存消耗:42.8 MB,击败了 42.32% 的 Java 用户

解题二:双指针 进阶版

思路

按照解题一的思维,我们可以从最大值开始比较并存放

  1. minIndex 从 0 开始,maxIndex 从 nums.length 开始,这样是为了数组中存在负数时,大值必定在两端
  2. 比较 nums[minIndex] 和 nums[maxIndex] 取最大值,放入 result 最后
  3. minIndex 右移,maxIndex 左移,直到相遇

代码

class Solution {
    public int[] sortedSquares(int[] nums) {
        int n = nums.length;
        int[] ans = new int[n];
        int length = nums.length;
        int leftIndex = 0;
        int rightIndex = length - 1;
        int[] result = new int[length];
        int index = rightIndex;
        while (leftIndex <= rightIndex) {
            int minValue = nums[leftIndex] * nums[leftIndex];
            int maxValue = nums[rightIndex] * nums[rightIndex];
            if (minValue > maxValue) {
                // 左端值较大
                result[index--] = minValue;
                leftIndex++;
            } else {
                result[index--] = maxValue;
                rightIndex--;
            }
        }
        return result;
    }
}

总结

性能分析

  • 执行耗时:1 ms,击败了 100.00% 的 Java 用户
  • 内存消耗:43 MB,击败了 57.23% 的 Java 用户