给你一个按 `非递减顺序` 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
示例 1:
输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]
示例 2:
输入:nums = [-7,-3,2,3,11]
输出:[4,9,9,49,121]
这里有个疑问解答一下,什么是非递减顺序
“递减数列”是“i<j时,A[i]>A[j]”,
“非递减数列”就是“递减数列”的补集,即“i<j时,A[i]<A[j]或A[i]=A[j]”
方案一:直接排序
// 直接排序
public static int[] sort(int[] nums) {
int[] newArr = new int[nums.length];
for (int i = 0; i < nums.length; i++) {
newArr[i] = (int) Math.pow(nums[i], 2);
}
Arrays.sort(newArr);
return newArr;
}
方案二:双指针
关于非递减数列大抵有一下几种情况:
// 1
[-5, -4, -3, -2, -1]
平方后 25 16 9 4 1 是个递减数列
// 2
[-3, -2, 0, 3, 5]
平方后 9 4 0 9 25 是个乱序数列
// 3
[0, 3, 5, 7, 8]
平方后 0 9 25 49 64 是个递增数列
我们可以设置两个指针left和right分别指向数组的开头和末尾。每次循环中,比较nums[left]2和nums[right]2的大小,将最大的那个值逆序放入答案数组的末尾,随后改变相应的指针
// 双指针
public static int[] sortedSquares2(int[] nums) {
int n = nums.length;
int[] ans = new int[n];
for (int left = 0, right = n - 1, pos = n - 1; left <= right; ) {
// 如果左侧平方值大于右边,放置新数组最大位置,然后继续比较left+1位置
if (nums[left] * nums[left] > nums[right] * nums[right]) {
ans[pos] = nums[left] * nums[left];
left++;
} else {
// 如果左侧小于右侧,则右侧平方值放置新数组最大位置,然后继续比较right-1位置
ans[pos] = nums[right] * nums[right];
right--;
}
pos--;
}
return ans;
}