排序题目:有序数组的平方

文章目录

题目

标题和出处

标题:有序数组的平方

出处:977. 有序数组的平方

难度

2 级

题目描述

要求

给定按非递减顺序 排序的整数数组 nums \texttt{nums} nums,返回每个数字的平方组成的新数组,要求也按非递减顺序排序。

示例

示例 1:

输入: nums = [-4,-1,0,3,10] \texttt{nums = [-4,-1,0,3,10]} nums = [-4,-1,0,3,10]

输出: [0,1,9,16,100] \texttt{[0,1,9,16,100]} [0,1,9,16,100]

解释:平方后,数组变为 [16,1,0,9,100] \texttt{[16,1,0,9,100]} [16,1,0,9,100]。排序后,数组变为 [0,1,9,16,100] \texttt{[0,1,9,16,100]} [0,1,9,16,100]。

示例 2:

输入: nums = [-7,-3,2,3,11] \texttt{nums = [-7,-3,2,3,11]} nums = [-7,-3,2,3,11]

输出: [4,9,9,49,121] \texttt{[4,9,9,49,121]} [4,9,9,49,121]

数据范围

  • 1 ≤ nums.length ≤ 10 4 \texttt{1} \le \texttt{nums.length} \le \texttt{10}^\texttt{4} 1≤nums.length≤104
  • -10 4 ≤ nums[i] ≤ 10 4 \texttt{-10}^\texttt{4} \le \texttt{nums[i]} \le \texttt{10}^\texttt{4} -104≤nums[i]≤104
  • nums \texttt{nums} nums 已按非递减顺序排序

进阶

计算每个元素的平方并对新数组排序的解法很简单,你可以使用不同的方法找到时间复杂度 O(n) \texttt{O(n)} O(n) 的解法吗?

解法一

思路和算法

最直观的解法是依次计算数组 nums \textit{nums} nums 中的每个元素的平方并存入新数组中,然后对新数组按非递减顺序排序,即可得到排序后的新数组。

代码

java 复制代码
class Solution {
    public int[] sortedSquares(int[] nums) {
        int length = nums.length;
        int[] squares = new int[length];
        for (int i = 0; i < length; i++) {
            squares[i] = nums[i] * nums[i];
        }
        Arrays.sort(squares);
        return squares;
    }
}

复杂度分析

  • 时间复杂度: O ( n log ⁡ n ) O(n \log n) O(nlogn),其中 n n n 是数组 nums \textit{nums} nums 的长度。计算数组 nums \textit{nums} nums 中的每个元素的平方并存入新数组需要 O ( n ) O(n) O(n) 的时间,对新数组排序需要 O ( n log ⁡ n ) O(n \log n) O(nlogn) 的时间,因此时间复杂度是 O ( n log ⁡ n ) O(n \log n) O(nlogn)。

  • 空间复杂度: O ( log ⁡ n ) O(\log n) O(logn),其中 n n n 是数组 nums \textit{nums} nums 的长度。对新数组排序需要 O ( log ⁡ n ) O(\log n) O(logn) 的递归调用栈空间。注意返回值不计入空间复杂度。

解法二

思路和算法

解法一没有利用到数组 nums \textit{nums} nums 已经按非递减顺序排序的条件,因此需要对新数组排序,时间复杂度是 O ( n log ⁡ n ) O(n \log n) O(nlogn)。如果利用数组 nums \textit{nums} nums 已经按非递减顺序排序的条件,则不需要对新数组排序,将时间复杂度降低到 O ( n ) O(n) O(n)。

由于一个数的平方大小与这个数的绝对值有关,因此考虑数组 nums \textit{nums} nums 中的绝对值最大元素与绝对值最小元素可能出现的位置。

数组 nums \textit{nums} nums 按非递减顺序排序,可能有以下三种情况:

  • 数组 nums \textit{nums} nums 的所有元素都是非负数,元素顺序为绝对值非递减顺序,首个元素的绝对值最小,末尾元素的绝对值最大;

  • 数组 nums \textit{nums} nums 的所有元素都是非正数,元素顺序为绝对值非递增顺序,首个元素的绝对值最大,末尾元素的绝对值最小;

  • 数组 nums \textit{nums} nums 中既有正数也有负数,首个元素或末尾元素的绝对值最大。

对于上述三种情况中的任意一种情况,绝对值最大的元素一定是数组 nums \textit{nums} nums 的首个元素或末尾元素。因此可以从数组 nums \textit{nums} nums 的两端向中间遍历,按照绝对值从大到小的顺序依次遍历数组 nums \textit{nums} nums 的元素,计算每个元素的平方,反向填入新数组。

具体做法是,维护两个下标 index 1 \textit{index}_1 index1 和 index 2 \textit{index}_2 index2,初始时 index 1 \textit{index}_1 index1 指向数组 nums \textit{nums} nums 的首个元素, index 2 \textit{index}_2 index2 指向数组 nums \textit{nums} nums 的末尾元素。遍历过程中,比较 nums [ index 1 ] \textit{nums}[\textit{index}_1] nums[index1] 和 nums [ index 2 ] \textit{nums}[\textit{index}_2] nums[index2] 这两个元素的绝对值:

  • 如果 nums [ index 1 ] \textit{nums}[\textit{index}_1] nums[index1] 的绝对值大于 nums [ index 2 ] \textit{nums}[\textit{index}_2] nums[index2] 的绝对值,则将 nums [ index 1 ] \textit{nums}[\textit{index}_1] nums[index1] 的平方填入新数组,将 index 1 \textit{index}_1 index1 加 1 1 1;

  • 如果 nums [ index 1 ] \textit{nums}[\textit{index}_1] nums[index1] 的绝对值小于等于 nums [ index 2 ] \textit{nums}[\textit{index}_2] nums[index2] 的绝对值,则将 nums [ index 2 ] \textit{nums}[\textit{index}_2] nums[index2] 的平方填入新数组,将 index 2 \textit{index}_2 index2 减 1 1 1。

由于遍历数组 nums \textit{nums} nums 的过程中,每次遍历的元素都是尚未遍历的元素中的绝对值最大的元素,因此遍历元素的顺序是绝对值非递增顺序,即元素的平方非递增顺序。将遍历的元素的平方反向填入新数组,新数组中的元素顺序为非递减顺序。

代码

java 复制代码
class Solution {
    public int[] sortedSquares(int[] nums) {
        int length = nums.length;
        int[] squares = new int[length];
        int index1 = 0, index2 = length - 1;
        for (int i = length - 1; i >= 0; i--) {
            if (Math.abs(nums[index1]) > Math.abs(nums[index2])) {
                squares[i] = nums[index1] * nums[index1];
                index1++;
            } else {
                squares[i] = nums[index2] * nums[index2];
                index2--;
            }
        }
        return squares;
    }
}

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是数组 nums \textit{nums} nums 的长度。需要遍历数组 nums \textit{nums} nums 中的每个元素一次。

  • 空间复杂度: O ( 1 ) O(1) O(1)。注意返回值不计入空间复杂度。

相关推荐
吗喽对你问好1 天前
华为5.7机考第一题充电桩问题Java代码实现
java·华为·排序
yxc_inspire8 天前
常见排序算法记录和理解
算法·排序
Tisfy24 天前
LeetCode 2563.统计公平数对的数目:排序 + 二分查找
python·算法·leetcode·二分查找·题解·排序
大熊猫侯佩1 个月前
“群芳争艳”:CoreData 4 种方法计算最大值的效率比较(上)
swift·排序·sort·array·coredata·nsarray·最大值 max
ゞ 正在缓冲99%…1 个月前
leetcode75.颜色分类
java·数据结构·算法·排序
_extraordinary_2 个月前
笔试专题(四)
算法·动态规划·贪心·模拟·排序·双指针
JLU_LYM2 个月前
有序数组双指针问题
排序·双指针·有序数组
wanjiazhongqi2 个月前
常见的排序算法 【复习笔记】
笔记·算法·排序
Kevin Kou2 个月前
编程题-最大数(中等)
数据结构·c++·算法·排序
菠菠萝宝3 个月前
【Java八股文】10-数据结构与算法面试篇
java·开发语言·面试·红黑树·跳表·排序·lru