持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第18天,点击查看活动详情
题目来源
题目介绍
给你一个按 非递减顺序 排序的整数数组
nums
,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
题目分析
根据题目首先要理解需要做的是啥,找出关键点。
1.已知非递减顺序整数数组nums。
2.返回一个新数组。
3.新数组元素根据nums里的每个元素的平方组成。
4.新数组要按非递减顺序排序。
综上所述,我们应该有一个新数组变量,用来存放nums数组平方后的元素,第二步将他们做个升序排序。
题目解答
一般解法
这种确实相对低效,当然也是最好理解的,虽然也能得出正确结果,不过循环太多了,主要就是利用了冒泡排序。
/**
* @param {number[]} nums
* @return {number[]}
*/
var sortedSquares = function(nums) {
let n = nums.length;
let newNums = new Array(n).fill(0);
for(let i=0;i<n;i++){
newNums[i]=nums[i]*nums[i]
}
for(let i=0;i<n;i++){
for (j = 0; j < n - i; j++) {
//根据数组长度以及i的值定义内循环次数,每次比较两个数的大小
if (newNums[j] > newNums[j + 1]) {
let temp=newNums[j]
newNums[j]=newNums[j+1]
newNums[j+1]=temp
}
}
}
return newNums;
};
双指针解法
一说到双指针就知道应该是从数组首尾开始比较。
这里我们用一个K表示新数组的下标,并且初始值设置为最大下标,用来为其赋值,这个解法就是在一个循环里把新数组排序好在输出。
数组从左下标 跟右下标比较开始,分别求出左边下标和右边下标元素的平方,因为不能递减,我们这里按递增处理,所以要比较大小。
如果平方后left<right,那么将right赋值给新数组最大下标k,然后让k-1,同时right往右移动一个值。
如果平方后left<right,那么left赋值给新数组下标为k的元素,同时left往前移动一个值。
这样可以保证新数组的顺序肯定是按升序来的。
/**
* @param {number[]} nums
* @return {number[]}
*/
var sortedSquares = function(nums) {
let n = nums.length;
let newNums = new Array(n).fill(0);
let i = 0, j = n - 1, k = n - 1;
while (i <= j) {
let left = nums[i] * nums[i],
right = nums[j] * nums[j];
if (left < right) {
newNums[k--] = right;
j--;
} else {
newNums[k--] = left;
i++;
}
}
return newNums;
};
官方解答
我们可以使用两个指针分别指向位置 00 和 n-1n−1,每次比较两个指针对应的数,选择较大的那个逆序放入答案并移动指针。
思路是一样的,不过我们用了while循环,这里用for循环,其实本质一样。
class Solution {
public int[] sortedSquares(int[] nums) {
int n = nums.length;
int[] ans = new int[n];
for (int i = 0, j = n - 1, pos = n - 1; i <= j;) {
if (nums[i] * nums[i] > nums[j] * nums[j]) {
ans[pos] = nums[i] * nums[i];
++i;
} else {
ans[pos] = nums[j] * nums[j];
--j;
}
--pos;
}
return ans;
}
}
总结
再一次见证了双指针解法解答数组类题目,真的很实用,双指针解法解决数组类算法题必须要掌握。