题目:
给你一个按 非递减顺序 排序的整数数组 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 已按 非递减顺序 排序
看到题觉得很简单,要么将数组内数组平方后排序,或者先将数字的绝对值排序再平方,写出的代码如此。
//思路,先平方,再排序
int count=-1;
for(int i=0;i<nums.size();i++){
nums[i]=nums[i]*nums[i];
}//插入排序
for(int i=1;i<nums.size();i++){
int key=nums[i];
int j=i-1;
while((j>=0)&&nums[j]>key){
nums[j+1]=nums[j];
j--;
}
nums[j+1]=key;
}
return nums;
不过做对了但显示超出时间限制。
其他博主的代码
这是官方解答。
- 直接排序思路:
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
vector<int> ans;
for (int num: nums) {//遍历
ans.push_back(num * num);//插入数字
}
sort(ans.begin(), ans.end());//排序
return ans;
}
};
他的直接排序思路是创建了一个vector数组,然后将平方的数放到另一个数组里面。直接用 sort 排序。
新手 表示没有看懂for循环里面写的什么,所以搜了一下:
nums是一个数组,里面放的是int类型的数据,然后定义了一个int类型的变量num,每循环一次,就从nums数组中取出一个数据来打印。int :表示你要遍历的集合的类型 nums:表示你要遍历的集合的名 num:表示你每遍历集合中一个元素 便存储到该变量。
就说“:”相当于一个in的意思。
- 双指针
双指针的思路大致是将负数与正数分成两部分分别平方再合并。
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int n = nums.size();
int negative = -1;
for (int i = 0; i < n; ++i) {
if (nums[i] < 0) {
negative = i;
} else {
break;
}
}//以上是计算负数与正数的分割线
vector<int> ans;
int i = negative, j = negative + 1;//从j后面开始就是正数
while (i >= 0 || j < n) {//i代表的是负数数量,n-j是正数数量
if (i < 0) {//小于0说明只剩下正数,直接记录(正数数量大于负数数量,且负数已全部插入完毕)
ans.push_back(nums[j] * nums[j]);
++j;//正数是从小到大排,所以是j++
}
else if (j == n) {//只剩下负数,倒序插入(负数数量大于正数数量,且正数已全部插入)
ans.push_back(nums[i] * nums[i]);
--i;//负数是从大到小排,所以是i--
}
else if (nums[i] * nums[i] < nums[j] * nums[j]) {//若最小的负数小于最小的正数,先插入负数
ans.push_back(nums[i] * nums[i]);
--i;
}
else {//否则先插入正数
ans.push_back(nums[j] * nums[j]);
++j;
}
}
return ans;
}
};
妙啊,几种情况写得明明白白。
- 方法三
方法三,其实就是将两个指针从两边往中间靠拢,将大的逆序放入新的指针中。
呜呜呜只能说太厉害了,我完全没想到过。
public:
vector<int> sortedSquares(vector<int>& nums) {
int n = nums.size();
vector<int> ans(n);//这里与前者不一样,这里用到了下标,所以在创建的时候需要用到ans(n)
for (int i = 0, j = n - 1, pos = n - 1; i <= j;) {//为什么for循环中是这个?前面是几个值得初始化,包括两个指针与现在的位置
if (nums[i] * nums[i] > nums[j] * nums[j]) {
ans[pos] = nums[i] * nums[i];
++i;
}
else {
ans[pos] = nums[j] * nums[j];
--j;//j与i的变化原理与前一个做法相同
}
--pos;//前一个位置
}
return ans;
}
};
倒着放数字大的,我想了想,那也许也可以正着放小的,不过那样需要找到正负分界线,比这个又麻烦了一点。
这位大佬总结了众多排列算法,可以用于复习
好了这道题就到此为止了~