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 <= A.length <= 10000
-10000 <= A[i] <= 10000
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()复杂度的循环,导致速度没有多少提升。所以说拆分并抽象问题的能力很重要。如果问两个有序数组合并成为一个有序数组怎么做,相信很多人都会做,但是如果放到这道题里边,比如我,就犯了低级的错误(这段失败的代码放在了文章最后)。
话不多说,放速度更快的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提问”按钮问我问题,我将竭力解答你的疑惑。