LeetCode 977——Squares of a Sorted Array

版权声明:欢迎评论和转载,转载时请注明作者和出处,共同维护良好的版权和知识产权秩序。 https://blog.csdn.net/CrazyOnes/article/details/87923380

Given an array of integers A sorted in non-decreasing order, return an array of the squares of each number, also in sorted non-decreasing order.

Example 1:

Input: [-4,-1,0,3,10]
Output: [0,1,9,16,100]

Example 2:

Input: [-7,-3,2,3,11]
Output: [4,9,9,49,121]

Note:

  1. 1 <= A.length <= 10000
  2. -10000 <= A[i] <= 10000
  3. A is sorted in non-decreasing order.

解决这道题不算难,难点在于如何更快速、更简洁的解决这个问题。

那么我们从最直接的思路开始,一步一步深入思考。

首先最直接最直白的方法就是直接对数组的每个元素进行平方后,再排序,就是最终结果。

AC代码如下:

class Solution {
    public int[] sortedSquares(int[] A) {
        //从最快速度上考虑,每次都会重复取A.length
        //所以使用int N = A.length会更快
        for (int i = 0; i < A.length; ++i) {
            A[i] = A[i] * A[i];
        }

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

很明显,这样不是最优的解法,为什么?因为我们没有充分里用题目中的条件,题目中说给出的数组A是一个按照非递减顺序排序的数组,这个条件无论有没有,我们的上述解法都可以正确运行,由此我们可以试着思考,是不是有一种方法,可以充分利用题目中的条件,从而达到更快的速度。

既然数组A是按照非递减顺序排列的,那么将他们平方之后的结果是什么呢。

对于数组[-4, -1, 0, 3, 10]来说:

  • 平方前:[-4, -1, 0, 3, 10]
  • 平方后:[16, 1, 0, 9, 100]

可以看出按照正数和负数对数组进行划分,平方之后这两个部分仍然是有序的,只不过负数部分是递减的顺序,正数部分是递增的顺序。也就是说,只要找到正数和负数交界处,就可以获得两个有序子数组。

到这里,本来接下来的思路已经很清晰了,但是偏偏我在这里脑子转不过去,仍然写了一个近似O(N^{2})复杂度的循环,导致速度没有多少提升。所以说拆分并抽象问题的能力很重要。如果问两个有序数组合并成为一个有序数组怎么做,相信很多人都会做,但是如果放到这道题里边,比如我,就犯了低级的错误(这段失败的代码放在了文章最后)。

话不多说,放速度更快的AC代码:

class Solution {
    public int[] sortedSquares(int[] A) {
        int p = A.length;
        
        for (int i = 0; i < A.length; ++i) {
            // 找到正负数的交界处
            if (A[i] >= 0 && p == A.length) {
                p = i;
            }
            // 在循环的同时求出每个元素的平方
            A[i] = A[i] * A[i];
        }
        int n = p - 1;

        int i = 0;
        // 创建新数组存放结果
        int[] result = new int[A.length];
        while (n >= 0 && p < A.length) {
            if (A[n] > A[p]) {
                result[i++] =  A[p++];
            } else {
                result[i++] = A[n--];
            }
        }

        // 将剩余的正数或负数放入结果中
        while (n >= 0) {
            result[i++] = A[n--];
        }
        while (p < A.length) {
            result[i++] = A[p++];
        }

        return result;
    }
}

失败的AC代码:

class Solution {
    public int[] sortedSquares(int[] A) {
        int index = A.length;
        // 求正负数的交界点
        for (int i = 0; i < A.length; ++i) {
            if(A[i] >= 0) {
                index = i;
                break;
            }
        }

        int num = A.length - index;
        // 每次将最后的元素插入到前边,类似于插入排序
        for (int i = 0; i < A.length && num > 0; ++i) {
            int tempValue = A[A.length - 1];
            if (Math.abs(A[i]) < tempValue) {
                for (int j = A.length - 1; j > i; --j) {
                    A[j] = A[j - 1];
                }
                A[i] = tempValue;
                --num;
            }
        }

        // 创建新数组并存储元素的平方和
        int []result = new int[A.length];
        for (int i = 0; i < A.length; ++i) {
            result[A.length - 1 - i] = A[i] * A[i];
        }

        return result;
    }
}

如有错误,欢迎指摘。也欢迎通过左上角的“向TA提问”按钮问我问题,我将竭力解答你的疑惑。

猜你喜欢

转载自blog.csdn.net/CrazyOnes/article/details/87923380