提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
包含两种解法,暴力排序和利用原数组的非递减性质采用双指针进行排序。
题目描述
链接: 997.有序数组的平方
给你一个按 非递减顺序 排序的整数数组 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) 的算法解决本问题
一、暴力排序
解题思路
先进行平方,在进行正常的数组排序。
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* sortedSquares(int* nums, int numsSize, int* returnSize) {
// 先将整个数组进行平方
for(int i = 0; i < numsSize; i++){
nums[i] = nums[i] * nums[i];
}
// 冒泡排序
for(int i = numsSize - 1; i > 0 ; i--){
for(int j = 0; j < i; j++){
if(nums[j] > nums[j+1]){
int tmp = nums[j];
nums[j] = nums[j + 1];
nums[j + 1] = tmp;
}
}
}
*returnSize = numsSize;
return nums;
}
二、双指针
1.解题思路
原数组具有非递减的性质,而最后要得到的数组也是一个非递减数组。利用这一良好性质,可将算法进行优化。
如原数组中都为非负数,则平方后的数组元素顺序无需改变。因此我们需要重点考虑的就是,原数组中存在负数元素的情况。
如果原数组中存在负数,平方后很可能成为和数组正数部分的元素相比较大的那个。这时候,若要正确排序,涉及到大量元素的移动,为方便需要创建一个新的数组。注意这里的新数组创建需要将动态分配数组空间。
2.形象理解
如下图所示,平方后的数组元素整体呈现一个了“两头重中间轻”的状态。最大的数组元素不是在最左侧就是在最右侧,对此我们创建两个指针“left”和“right”来指向数组的最左侧和最右侧。比较“left”和“right”所指向的元素,较大的那一个即为最大的数组元素,将此元素赋值给新数组。若较大的数组元素为“left”所指的,则下一步将“left”右移;否则将“right”左移,直到将新数组填满。
3.代码
代码如下:
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* sortedSquares(int* nums, int numsSize, int* returnSize) {
int left, right;
int* ans = (int*)malloc(sizeof(int) * numsSize); // 动态分配数组空间
left = 0;
right = numsSize - 1;
int idx = numsSize - 1;
while(left <= right){
if(nums[left]*nums[left] >= nums[right]*nums[right]){
ans[idx] = nums[left]*nums[left];
left++;
}else{
ans[idx] = nums[right]*nums[right];
right--;
}
idx--;
}
*returnSize = numsSize;
return ans;
}