977.有序数组的平方
作者:互联网
给你一个按 非递减顺序 排序的整数数组 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,将它平方后填入结果数组中,然后设定两个指针一个为i - 1,一个为i + 1,分别向两边扩展,两个指针每次指到的数中肯定有下一个平方最小的数,做一次判断后将该数填入数组,并且将该指针向左或向右移一位,这里要注意边界情况,一边的指针越界说明这一边的数已经填完了,只需要按顺序填另一边的数了。
倒序
正序方法需要先遍历找到绝对值最小的数,如果数组全是负数则需要遍历整个数组,后续又会涉及到边界条件,增加了不少的时间复杂度和代码量。
我们可以倒序填入结果,首先观察到原数组最两边的数中一定有该数组中绝对值最大的数,那么我们接下来要做的就和刚才讲的差不多了,设定两个指针left = 0和right = nums.length - 1,分别指向原数组的最左边和最右边,然后比较这两个数的绝对值大小,将较大的那一个填入结果数组的最右边,同时指针向内移动一位,接着比较,以从尾到头的方式填满结果数组后返回。
这种方法其实不容易想到,但是又在很多题中出现,就本题而言,相比正序减少了时间上的开销也简化了代码,最后完整代码如下:
class Solution { public int[] sortedSquares(int[] nums) { int[] res = new int[nums.length]; //初始化结果数组 int left = 0; //头指针指向数组最左边 int right = nums.length - 1; //尾指针指向数组最右边 for (int i = nums.length - 1; i >= 0; i--) { //倒序遍历结果数组 //当左指针指向的数平方后大于等于右指针平方后的数,将该结果填入结果数组,左指针向右移动一位 if (nums[left] * nums[left] >= nums[right] * nums[right]) { res[i] = nums[left] * nums[left]; left++; //当右指针指向的数平方后大于等于左指针平方后的数,将该结果填入结果数组,右指针向左移动一位 }else { res[i] = nums[right] * nums[right]; right--; } } return res; //遍历结束,返回结果 } }
原文:https://leetcode.cn/problems/squares-of-a-sorted-array/solution/by-nice-hermann9a2-qqft/
标签:977,平方,right,nums,int,数组,指针 来源: https://www.cnblogs.com/liangren-na/p/16437594.html