第一眼想法我想绝大数人 一定是和我一样 平方再排序
然后就是这样了
class Solution {
public int[] sortedSquares(int[] nums) {
int[] ans = new int[nums.length];
for (int i = 0; i < nums.length; ++i) {
ans[i] = nums[i] * nums[i];
}
Arrays.sort(ans);
return ans;
}
}
但是结果很拉 32% 51%
既然我们十来学习算法的 肯定是不能只此而已 今天就一起来学习一下 双指针
双指针是是什么?两个指针 学过C的应该能懂
我们最开始的方法 有一个条件没有利用到「数组 nums 已经按照升序排序」
这个时候我们就可以分情况讨论了,当全是正数, 直接平方自然就是升序
同理全是负数时,平方就是降序
这个时候问题就来了 一半正数 一半负数怎么办?
找到分界线 没错就是这样
这个时候我们就可以用一个排序算法 归并排序
具体地,我们设 neg 为数组 nums 中负数与非负数的分界线,也就是说,nums[0] 到 nums[neg] 均为负数,而 nums[neg+1] 到nums[n−1] 均为非负数。当我们将数组 nums 中的数平方后,那么nums[0] 到 nums[neg] 单调递减,nums[neg+1] 到nums[n−1] 单调递增。就像上图
class Solution {
public int[] sortedSquares(int[] nums) {
int n = nums.length;
int negative = -1;
for (int i = 0; i < n; ++i) {
if (nums[i] < 0) {
negative = i;
} else {
break;
}
}
int[] ans = new int[n];
int index = 0, i = negative, j = negative + 1;
while (i >= 0 || j < n) {
if (i < 0) {
ans[index] = nums[j] * nums[j];
++j;
} else if (j == n) {
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;
}
}
双指针算法小结:
- 将两个有序的子序列归并为一个单一的有序序列
- 双指针算法指的是在重复遍历对象的过程中,不是在两个循环中使用单个指针进行重复访问,而是在一个循环中使用两个相同方向(快慢指针)或者相反方向(对撞指针)的指针进行访问。