题目描述:
给你一个按 非递减顺序 排序的整数数组 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]
提示:
- 1 <= nums.length <= 104
- -104 <= nums[i] <= 104
- nums 已按 非递减顺序 排序
思路:
最简单的方式一看便知,如题目所说的,先平方后直接排序,但是这样是学不到东西的。在题目的分类中可以看到这道题是双指针算法的经典应用。下面我来解释:nums是已经排序好的数组,若是只存在负数,那平方过后的数组是以降序排列。若只存在正数,那平方过后依然是升序排列的数组。由此可知,我们应该将原数组分成正负两个区域,方式1是通过找到数组的正负分界线(0为正数)neg,将数组拆分成两个,创建两个指针 分别指向neg (负数数组的最小值)和neg+1(正数数组的最小值),使前者往后移动,后者往前移动,往新数组中放入值,完成排序返回
实际上还有更好的方式,上一种方式会因为正负数组长度的不同,导致我们需要在其中一个数组到达长度以后去处理剩下的指针移动方式,而我们可以直接从在新数组中从后往前放(两个指针也应从相应的指向其数组中的最小值更换为最大值,如:本指向nums[neg] 和nums[neg+1]的两个值应指向nums[0]和nums[nums.length-1],使指针相向移动的同时进行比较,而不用去处理其中一个数组结束的情况
误区:
在思考题解的过程中,会为了解题而直接去使用先平方后直接sort排序的方法,这样对算法能力的提升并不大,应该使用双指针去完成解题,效率会更快,自己也能学到东西
题解:
public int[] sortedSquares(int[] nums) {
//创建答案数组
int[] ans = new int[nums.length];
//创建左右指针,分别在数组的头尾
int left = 0, right = nums.length-1;
//创建答案数组的下标指针
int index = ans.length-1;
while(left <= right){
//这里用到一个三元计算,需要关注的点为1、index--,含义是
//从答案数组的最后添加一个数组后指针向前位移一位,2、right--和
//left++,含义是是:在完成判断以后,根据添加情况,将左或右指针
//向前或后位移一位,若不位移left和right会导致while永远为真,而
//index一直自减,最后抛出下标越界异常导致错误
ans[index--] = nums[right]*nums[right]>nums[left]*nums[left]?nums[right]*nums[right--]:nums[left]*nums[left++];
}
return ans;
}