题目
难度简单184
给定一个按非递减顺序排序的整数数组 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
已按非递减顺序排序。
分析
由于非递减中包含了负数,负数平方后会打乱整个排序。
平方前[-4,-1]-->平方后[16,1]
所以负数的升序,平方后就是降序。
如果全是负数,只要将原有序列倒转下。
如果去拿时整数,其实还是原有的书序。
如果前面是负数,我们需要找到最后一个负数的位置。其与其前面的元素平方后,组成了新的降序序列。
平方后:
上面的序列可以人为是两个序列,以最小负数的平方为分界点。
然后再合并两个序列为一个有序序列。整个题目就装换成了 88. 合并两个有序数组。唯一区别就是第一个序列是降序,第二个序列是升序。
代码显示
- 找到最小的负数,作为查分序列的中点。
//用来存储新的有序序列
int[] result = new int[nums.length];
//最小负数的位置
int midIndex = -1;//可能并不存在,如果都是正数,所以默认值是-1
for (int i = 0; i < nums.length; i++) {
if (nums[i] < 0) {
midIndex = i;
}
nums[i] = nums[i] * nums[i];
}
2 . midIndex作为负数列表平方的降序的起点,midIndex+1作为原有正数序列的升序的起点。然后每次分别从没序列取出一个值进行比较,小的值放在新序列的前面。
int zIndex = midIndex + 1;
int cur = 0;
while ( cur <nums.length) {
if (nums[zIndex] > nums[midIndex]) {
result[cur++] = nums[midIndex--];
} else {
result[cur++] = nums[zIndex++];
}
}
return result;
- 需要注意临界点的处理,比如整个序列都是负数,那么midIndex就是nums.length-1。或者整个序列都是正数,那么midIndex=-1。此时需要注意角标越界的处理。
完整代码如下:
public int[] sortedSquares(int[] nums) {
int[] result = new int[nums.length];
int midIndex = -1;
for (int i = 0; i < nums.length; i++) {
if (nums[i] < 0) {
midIndex = i;
}
nums[i] = nums[i] * nums[i];
}
int zIndex = midIndex + 1;
int cur = 0;
while ( cur <nums.length) {
if(midIndex<0){
result[cur++] = nums[zIndex++];
}else if(zIndex>=nums.length){
result[cur++] = nums[midIndex--];
}else if (nums[zIndex] > nums[midIndex]) {
result[cur++] = nums[midIndex--];
} else {
result[cur++] = nums[zIndex++];
}
}
return result;
}