题目名称:移动零
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
示例:
输入: [0,1,0,3,12]
输出: [1,3,12,0,0]
说明:
必须在原数组上操作,不能拷贝额外的数组。 尽量减少操作次数。
解法
一、中规中矩双指针
- 快慢双指针,j 是慢指针,i是快指针,i跟随遍历,如果遇到非0
- i和j相等就j++(同时i在循环中也加1了)
- i和j不相等就交换位置
/**
* @param {number[]} nums
* @return {void} Do not return anything, modify nums in-place instead.
*/
var moveZeroes = function (nums) {
let j = 0
for (let i = 0; i < nums.length; i++) {
if (nums[i] !== 0) {
if (i === j) {
j++
} else {
// 遇到非0元素了,要和0元素交换位置
[nums[j++], nums[i]] = [nums[i], nums[j]]
}
}
}
}
原理:
二、js数组的splice方法自身操作
- 不要手里拿着锤子,就看什么都是钉子,双指针虽好,但JavaScript本身遍历也不错
/**
* @param {number[]} nums
* @return {void} Do not return anything, modify nums in-place instead.
*/
var moveZeroes1 = function (nums) {
let count = 0
for (let i = 0; i < nums.length - count; i++) {
if (nums[i] === 0) {
nums.push(nums.splice(i, 1)[0])
count++
i--
}
}
}
- 原理很简单,从前往后遍历,只要遇到0,就splice删除并push到最后
- 每次执行一遍上述操作,需要遍历的数组长度-1
- 采用count计数,可以减少无效判断
三、双指针进化
- j是慢指针,i是快指针
- 从前向后遍历,如果
nums[i]
不为0,那么j所在位置设置为i值,i和j都加1 - 否则只有i加1,这样能保证j所处位置都是顺序排列的非零值
- 从前向后遍历,如果
/**
* @param {number[]} nums
* @return {void} Do not return anything, modify nums in-place instead.
*/
var moveZeroes2 = function (nums) {
let len = nums.length
let j = 0
for (let i = 0; i < len; i++) {
if (nums[i]) {
nums[j++] = nums[i]
}
}
for (let i = j; i < len; i++) {
nums[i] = 0
}
return nums
};
测试用例
// 测试用例
let test = [0, 1, 0, 3, 12]
let test1 = [0, 0, 1]
console.time('执行用时');
console.log(moveZeroes(test));
console.log(moveZeroes1(test));
console.log(moveZeroes2(test));
console.timeEnd('执行用时');
总结
- 数组的 splice 方法可以删除指定位置元素
nums.push(nums.splice(i, 1)[0])
可以同时进行,不会冲突
说明
- 本题解已同步leetcode-js-simple/08.[ 283 ] 移动零,可以复制代码进行调试。
- 总结出了一套亲测有效的前端无痛刷题项目,有助于算法小白平稳入门,详见leetcode-js-roadmap,希望对从零开始刷题的前端小伙伴们带来帮助~
本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!