持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第5天,点击查看活动详情
题目
- 分类:数组
- 难度(入门|中等|难):入门
- LeetCode链接
给你一个按非递减顺序 排序的整数数组 nums,返回每个数字的平方组成的新数组,要求也按非递减顺序 排序。
输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:
平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]
思路
-
理解要求: 非递减数组 --> 要求数组的后一个元素值大于等于前一个元素 --> 元素从小到大排序, 可以值重复的数组
-
难点: 由于存在负数值, 平方后大小顺序会打乱. 但打乱也不是全无规律
-
找规律:
- 在上述给出的例子中, 找到绝对值最小的元素值, 也就是0,
- 0以前的元素如果按绝对值排序, 是从大到小的有序序列
- 0以后的元素序列是从小到大的有序序列
-
解题要点:
- 本题的要求变为: 将两个有序序列, 组合为一个新的有序序列, 从小到大排序
- 借助两个指针, 一个指针从前往后走, 另一个指针从后往前走. 相当于分别按从大到小的顺序遍历了两个有序数组.
- 两个指针所指向的值相互比较, 将较大的插入新数组, 并且指针挪动, 另一个指针不动, 进入下一轮比较
- 不断遍历比较, 临界点为两指针相遇, 完成比较.
-
难点:
- 思路不好捋顺, 一旦理顺就演变为两个有序数组组合为新有序数组的问题.
- 临界点判断: 当两个指针相遇时, 共同指向的那个值的插入.
代码
class Solution {
public int[] sortedSquares(int[] nums) {
int[] newNums = new int[nums.length];
int front = 0;
int end = nums.length-1;
int count = end;
while(front<=end){
int multif = nums[front]*nums[front];
int multie = nums[end]*nums[end];
if(multif>multie){
newNums[count] = multif;
front++;
} else{
newNums[count] = multie;
end--;
}
count--;
}
return newNums;
}
}
代码要点:
count这个变量表示新数组要插入元素的位置的索引. 从数组最后往前插入.
-
while(front<=end), 里面的等号如何确定加不加?- 这就是临界条件, 加不加的依据是: 当两指针相等时, 共同指向最后这个待加入的元素, while的大括号后面的代码能否实现最后这个元素的插入? 如果不行, 就得在外面额外插入最后一个元素.
- 脑内模拟一下, 如果while里等号加上, 共同指向同一个元素时, 大括号内,
multif和multie的值相等, 进入else判断, 如果最后一个元素能成功赋值, 就得要count值此刻等于0, 而count从nums.length-1开始, 每插入一个元素就count--, 挪动到下一个待插入元素的位置, 此时还剩一个元素没插入, count指向最后一个待插入的位置, 也就是count=0, 满足要求, 能插入.
总结
- 如果题目有隐含数组遍历的要求, 那么就可以考虑双指针方法
- 这道题从看似无序到有序, 转折点就是要分清有序数组在哪儿. 所以能找出题目的原型很重要.