[数组][简单]977.有序数组的平方

博客围绕有序数组的平方排序问题展开。先给出题目,即给定非递减排序的整数数组,返回其元素平方组成的非递减排序新数组。接着介绍两种解答方法,一是排序法,时间复杂度 O(NlogN);二是双指针法,时间复杂度 O(N)。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


tags:

  • 简单
  • 参考
  • 数组
  • 双指针
    flag: green
    style: summer
    date: ‘2019-6-9’

977.有序数组的平方

一、题目:

给定一个按非递减顺序排序的整数数组 A,返回每个数字的平方组成的新数组,要求也按非递减顺序排序。

示例 1:

输入:[-4,-1,0,3,10]
输出:[0,1,9,16,100]
示例 2:

输入:[-7,-3,2,3,11]
输出:[4,9,9,49,121]

提示:

1 <= A.length <= 10000
-10000 <= A[i] <= 10000
A 已按非递减顺序排序。

二、解答

方法一:排序
思路与算法

创建一个新的数组,它每个元素是给定数组对应位置元素的平方,然后排序这个数组。

class Solution {
    public int[] sortedSquares(int[] A) {
        int N = A.length;
        int[] ans = new int[N];
        for (int i = 0; i < N; ++i)
            ans[i] = A[i] * A[i];

        Arrays.sort(ans);
        return ans;
    }
}

复杂度分析

  • 时间复杂度:O(Nlog⁡N)O(N \log N)O(NlogN),其中 N 是数组 A 的长度。

  • 空间复杂度:O(N)O(N)O(N)

方法二:双指针
思路

因为数组 A 已经排好序了, 所以可以说数组中的负数已经按照平方值降序排好了,数组中的非负数已经按照平方值升序排好了。

举一个例子,若给定数组为 [-3, -2, -1, 4, 5, 6],数组中负数部分 [-3, -2, -1] 的平方为 [9, 4, 1],数组中非负部分 [4, 5, 6] 的平方为 [16, 25, 36]。我们的策略就是从前向后遍历数组中的非负数部分,并且反向遍历数组中的负数部分。

算法

我们可以使用两个指针分别读取数组的非负部分与负数部分 —— 指针 i 反向读取负数部分,指针 j 正向读取非负数部分。

那么,现在我们就在使用两个指针分别读取两个递增的数组了(按元素的平方排序)。接下来,我们可以使用双指针的技巧合并这两个数组。

class Solution {
    public int[] sortedSquares(int[] A) {
        int N = A.length;
        int j = 0;
        while (j < N && A[j] < 0)
            j++;
        int i = j-1;

        int[] ans = new int[N];
        int t = 0;

        while (i >= 0 && j < N) {
            if (A[i] * A[i] < A[j] * A[j]) {
                ans[t++] = A[i] * A[i];
                i--;
            } else {
                ans[t++] = A[j] * A[j];
                j++;
            }
        }

        while (i >= 0) {
            ans[t++] = A[i] * A[i];
            i--;
        }
        while (j < N) {
            ans[t++] = A[j] * A[j];
            j++;
        }

        return ans;
    }
}

复杂度分析

  • 时间复杂度:O(N),其中 N 是数组 A 的长度。
  • 空间复杂度:O(N)。

自己代码

class Solution {
    public int[] sortedSquares(int[] A) {
        int j = 0;
        int []ans = new int[A.length];
        //这里尽量使用while,因为不确定小于0的个数,也就是循环的次数
        // for (int j = 0; j < A.length; j++) {
        //      if (A[j] < 0  ) {
        //          j++;
        //      }

        while(j < A.length && A[j] < 0){
            j++;
        }

        int i = j - 1;
        int t = 0;

        while(i >= 0 && j < A.length){
            if (A[i]*A[i] < A[j]*A[j]) {
                ans[t++] = A[i]*A[i];
                i--;
            }else{
                ans[t++] = A[j]*A[j];
                j++;           
          }
        }

        while(i >= 0){
            ans[t++] = A[i]*A[i];
            i--;
        }

        while(j < A.length){
            ans[t++] = A[j]*A[j];
            j++;
        }
       return ans;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值