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

文章目录

题目

标题和出处

标题:有序数组的平方

出处: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 ≤ numsi ≤ 10 4 \texttt{-10}^\texttt{4} \le \texttt{numsi} \le \texttt{10}^\texttt{4} -104≤numsi≤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 numsindex1 和 nums index 2 \textit{nums}\\textit{index}_2 numsindex2 这两个元素的绝对值:

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

  • 如果 nums index 1 \textit{nums}\\textit{index}_1 numsindex1 的绝对值小于等于 nums index 2 \textit{nums}\\textit{index}_2 numsindex2 的绝对值,则将 nums index 2 \textit{nums}\\textit{index}_2 numsindex2 的平方填入新数组,将 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)。注意返回值不计入空间复杂度。

相关推荐
aqiu1111111 小时前
【算法刷题】蓝桥杯:怎么倒茶(贪心算法 + 结构体排序)
贪心·排序
OuO-22 小时前
笔试强训 Day 43:kotori 和抽卡(二)、ruby 和薯条、循环汉诺塔
数学·前缀和·二分查找·动态规划·排序·滑动窗口·循环汉诺塔
Tisfy5 天前
LeetCode 3731.找出缺失的元素:哈希 / 排序
算法·leetcode·哈希算法·排序·哈希表
Tisfy14 天前
LeetCode 3016.输入单词需要的最少按键次数 II:排序(贪心)
linux·算法·leetcode·题解·贪心·排序·计数
Tisfy17 天前
LeetCode 3517.最小回文排列 I:排序(Python两行版) / 计数(O(n)时间+O(C)空间+字符串原地修改)
c语言·python·leetcode·字符串·排序·计数排序·回文
txzrxz19 天前
拓补排序讲解
c++·算法·图论·排序
汉克老师1 个月前
GESP2026年6月认证C++八级( 第三部分编程题(1、线网建设))精讲
c++·最小生成树·排序·kruskal·并查集·gesp8级
Tisfy1 个月前
LeetCode 1288.删除被覆盖区间:排序(非二重循环暴力)
算法·leetcode·题解·排序
hairenwangmiao2 个月前
c++排序(第一章----桶排序与sort排序)
数据结构·c++·排序
hairenwangmiao2 个月前
B4041 [GESP202409 四级] 区间排序
算法·排序