题目
给定一个按非递减顺序排序的整数数组 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 已按非递减顺序排序。
思路
情况①
数组里的元素都是非负数。
这种情况就比较好解决了,直接按顺序把每个元素平方输出就行。
情况②
数组里的元素都是非正数。
这种情况也比较好解决,直接按逆序把每个元素平方输出就行。
情况③
数组里有正数也有负数。
这种情况就比较复杂了。
首先,原数组有序,要得结果也是有序的,但原数组里的元素有正有负,而结果要的顺序是 元素平方之后的顺序,也就是原数组元素绝对值的顺序。
看成左右两个数组:
把前后两个数组都进行 “平方” 处理
把问题转换成:两个有序数组拼接成一个有序数组
这样我们就利用上了原数组有序的条件,尽量利用我们有的条件,才能达到最优解。
代码
public static void fun(int[] num) {
if (num.length == 1) {//只有一个元素的话,直接平方输出
System.out.print("[ ");
System.out.print(num[0] * num[0]);
System.out.print("]");
return;
}
if (num[0] < 0) {//如果第一个数小于零
int zero = -1;
for (int i = 0; i < num.length; i++) {
if (num[i] > 0) {
//寻找第一个大于 0 的元素
zero = i;
break;
}
}
if (zero == -1) {//说明没有大于0的元素(全是负数)
//直接逆序输出
System.out.print("[ ");
for (int i = num.length - 1; i >= 0; i--) {
System.out.print(num[i] * num[i] + " ");
}
System.out.print("]");
return;
}
//生成 结果数组
List<Integer> list = new ArrayList<>();
int left = zero - 1;
int right = zero;
int count = num.length;
while (count > 0) {
if ((num[left] * num[left]) > (num[right] * num[right])) {
list.add(num[right] * num[right]);
count--;
//如果right哨兵已经达到最右端了,
//问题就转换成了 左边数组剩余元素的平方的逆序排列了
if (right == (num.length - 1)) {
for (int i = 0; i < count; i++) {
list.add(num[left] * num[left]);
left--;
}
break;
}
right++;
} else {
list.add(num[left] * num[left]);
count--;
//如果left哨兵已经达到最左端了,
//问题就转换成了 右边数组剩余元素的平方的顺序排列了
if (left == 0) {
for (int i = 0; i < count; i++) {
list.add(num[right] * num[right]);
right++;
}
break;
}
left--;
}
}
System.out.print("[ ");
for (int a : list) {
System.out.print(a + " ");
}
} else {//说明第一个数也不小于零(全是正数)
//直接平方输出
System.out.print("[ ");
for (int a : num) {
System.out.print(a * a + " ");
}
}
System.out.print("]");
}
测试:
int[] arr = {-4,-2,0,1,3};
fun(arr);
结果:
[ 0 1 4 9 16 ]