Given an integer array nums sorted in non-decreasing order, return an array of the squares of each number sorted in non-decreasing order.
给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
//手撕 暴力法
class Solution {
public int[] sortedSquares(int[] nums) {
int length = nums.length;
for(int i = 0;i <length;i++){
nums[i]=nums[i]*nums[i];
}
Arrays.sort(nums);
return nums;
}
}
该方法直接对数组的元素进行本地平方,之后使用Arrays的sort方法进行升序排序即可得到答案。
//双指针 归并排序法
class Solution2 {
public int[] sortedSquares(int[] nums) {
int length = nums.length;
int mid = -1;
//寻找分界点
for(int i=0; i<length;i++){
if(nums[i]<0){
mid=i;
}else{
break;
}
}
int[] ans = new int[length];//初始化数组
int index=0;
int i=mid;
int j=mid+1;//刚好能从下标0开始
while(i>=0||j<length){
if(i<0){//数组全为正数时 和 负数添加完了
ans[index]=nums[j]*nums[j];
j++;
}else if(j==length){//数组全为负数时 和 正数添加完了
ans[index]=nums[i]*nums[i];
i--;
}else if(nums[i]*nums[i]<nums[j]*nums[j]){//左右两半向外扩散小的先插入
ans[index]=nums[i]*nums[i];
i--;
}else{
ans[index]=nums[j]*nums[j];
j++;
}
index++;
}
return ans;
}
}
该方法根据数组自身特性将数组划分为左右两半,经过平方后左右两半数组都满足非递减特性,符合归并排序算法的条件,将左右最小的平方数进行比较,较小的插入返回数组下标后移,其中一个数组元素插入完毕则将剩余的数组逐一插入在末尾即可。
// 首尾双指针法
class Solution3 {
public int[] sortedSquares(int[] nums) {
int length = nums.length;
int[] ans = new int[length];
for(int i=0,j=length-1,pos=length-1;i<=j;){//插入最后一个元素则跳出循环
if(nums[i]*nums[i]<nums[j]*nums[j]){//将较大的数倒插在返回数组末尾
ans[pos]=nums[j]*nums[j];
j--;
}else{
ans[pos]=nums[i]*nums[i];
i++;
}
pos--;//循环轮数控制变量
}
return ans;
}
}
该方法相比归并排序减少了对其中一个数组插入完毕的情况,减少了过多的判断,同时将pos设为0开始从头开始插入也是可以的,需要注意的是i和j可能为同一个下标即最后一个元素。