给你一个按 非递减顺序 排序的整数数组 ,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。 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已按 非递减顺序 排序
进阶:
● 请你设计时间复杂度为 O(n) 的算法解决本问题
题目描述:非递减数组nums,将各元素平方按非递减顺序排列,返回新数组
暴力法
//时间复杂度:O(n+nlogn) = O(nlogn)
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
for (int i = 0; i < nums.size(); i++) {
nums[i] *= nums[i];
}
sort(nums.begin(), nums.end()); //快速排序
return nums;
}
};
双指针
● 思路:
○ nums元素组成可能为:①全正;②全负;③有正有负;
○ 对于有正有负的情况,需要比较负数平方与正数平方,才能决定在新数组中的位置
○ 用一个指针扫描负数,一个指针扫描正数,①②可合并到③(一个指针始终未更新)
class Solution{
vector<int> sortedSquares(vector<int>& nums) {
vector<int> ans(nums.size(), 0);
int left = 0;
int right = nums.size() - 1;
for (int i = nums.size() -1; i >= 0; i--) { //这里只能倒着放
if (nums[left] * nums[left] > nums[right] * nums[right]) {
ans[i] = nums[left] * nums[left];
left++;
}
else {
ans[i] = nums[right] * nums[right];
right--;
}
}
return ans;
}
};
总结
双指针将一个两层循环转化成了一层循环,时间复杂度也从n^2变成了n
- 那么什么时候会需要使用双指针呢?
一般来讲,当遇到需要对一个数组进行重复遍历时,可以想到使用双指针法 - 如何实现将普通写法到双指针写法的转换呢?
说是指针,其实是设置两个int变量分别赋值为数组的首和尾,在一层循环内,每次只对其中一个指针进行移动,找到判断指针移动的条件是双指针的核心,在该题中,是一个求和为0的问题,那么当sum>0时,显然说明整体的值太大了,应该让其更小,故对于排序后的数组将尾指针左移,显然,sum和0的大小便是此题中判断指针移动的条件