持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第30天,点击查看活动详情
前言
天天改需求搞的我头皮发麻,来搞一道简单的算法题刷刷,有试试想想没事做做题还是挺爽的,能让脑子灵光点,哈哈哈
题目描述
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
示例 1:
输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]
示例 2:
输入: nums = [0]
输出: [0]
解题思路
这题需要注意的点如下
- 首先题目题目说了要在不复制数组的情况下来完成,那我们就不能声明新的数组了
- 题目中是说把0都移动到数组的尾部,那我们遍历一遍数组就可以了,遇到零就插入到数组的尾部
- 在插入的同时要把当前位置的0删除掉 代码如下:
/**
* @param {number[]} nums
* @return {void} Do not return anything, modify nums in-place instead.
*/
var moveZeroes = function(nums) {
let i =0
let count = 0
while(i<nums.length-count){
if(nums[i]===0){
nums.splice(i,1)
nums.push(0)
count++
}else{
i++
}
}
return nums
};
运行结果:
优化
上面的解法虽然可以满足题目的要求,但是由于使用了splice()以及push操作,都是很耗时的,下面给出一种更高级的解法,使用双指针。
- 首先,双指针都指向数组的头部
- 当指针i指向的数字是非零的时候就那i指向的值和l指向的值进行交换,交换之后l++
- 这种使用双指针的方法少了从新插入数据的步骤,因为运行速度更快 代码如下:
var moveZeroes = function (nums) {
let l = 0;
for (let i = 0; i < nums.length; ++i) {
if (nums[i] !== 0) {
swap(nums, i, l++);
}
}
return nums
};
var swap = function (nums, i, j) {
let temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
运行结果:
运行速度明显得到了提升,但其实还有优化的点,那就是目前代码中只要是非零就交换,这样是不合理的,因为存在自己和自己交换的情况,因此代码可以改为如下:
/**
* @param {number[]} nums
* @return {void} Do not return anything, modify nums in-place instead.
*/
var swap = function (nums, i, j) {
let temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
var moveZeroes = function (nums) {
let l = 0;
for (let i = 0; i < nums.length; ++i) {
if (nums[i] !== 0) {
if(i!==l){
swap(nums, i, l++);
}else{
l++
}
}
}
return nums
};
运行结果如下:
总结
代码总是有更优的解决办法,一般都是先做出来再一步步的优化,没有最好的代码,只有更好的代码。