字节跳动 2021 春招面试高频题1-有序数组的平方
问题描述
给定一个以升序排序的整数A数组,返回每个数字的平方的数组,也以排序的升序排序。
示例
输入:[-4,-1,0,3,10]
输出:[0,1,9,16,100]
输入:[-7,-3,2,3,11]
输出:[4,9,9,49,121]
解法
首先拿到一个算法题,除非是你做过,知道算法,或者是对算法了然于胸,可以一步到位,对于大多数的同学,可以先试着用暴力的方法先来考虑,首先,暴力的算法你能想到怎么做?
解法1
既然是求平方的数组,那是不是我可以第一步先把平方的数组算出来,第二步再来排序就可以了。这样是不是简单了很多呢,我们来看一下代码。
public int[] SquareArray(int[] A) {
if(A == null || A.length == 0) {
return A;
}
int[] result = new int[A.length];
int index = 0;
for(int number : A) {
result[index++] = number * number;
}
//这里偷懒了一下,你可以自己排序,也可以使用现成的,比如快速排序,因为面试不可能以这个作为最后答案,所以偷懒一下,使用现成的。
Arrays.sort(result);
return result;
}
代码如上,我们可以看到,简单暴力,主要的算法复杂度在于排序,使用快排的话,平均复杂度是nlog(n)。好,我们来看一下,那有没有什么办法可以减少时间复杂度呢。
解法2
解法1之所以慢了点,是因为我们先写出平方,然后再排序,那可不可以同时进行呢?当然可以,这就是经典的双指针。可以左右比着来,谁大我存谁,然后后面的大,向前移,前面的大,向后移,直到比完为止。代码如下。
public int[] SquareArray(int[] A) {
if(A == null || A.length == 0) {
return A;
}
int start = 0;
int end = A.length - 1;
int index = end;
int[] result = new int[A.length];
while(index >= 0) {
int numberStart = A[start] * A[start];
int numberEnd = A[end] * A[end];
if (numberEnd > numberStart) {
result[index--] = numberEnd;
end--;
} else {
result[index--] = numberStart;
start++;
}
}
return result;
}