题目
给定一个数组nums, 编写一个函数将所有 0 移动到它的末尾,同时保持非零元素的相对顺序。
例如, 定义 nums = [0, 1, 0, 3, 12],调用函数之后, nums 应为 [1, 3, 12, 0, 0]。
注意事项:
必须在原数组上操作,不要为一个新数组分配额外空间。
尽量减少操作总数。
解法一:
思路:查找出数组中所有的0,从数组中移除后立刻push到数组末尾。其中参数b用来记录移动数量,当索引为length-b时,后面的数已全部为0,可以中断遍历。i–的作用:从java的角度来说,数组元素是不能在for循环中删除的,因为这样会改变数组的长度,导致异常抛出,必须使用迭代器遍历数组才能安全删除元素,此处JavaScript的splice方法会直接改变数组长度,从而导致后面的元素索引变化,故需将索引向前移动一位,以确保无元素遗漏。
var moveZeroes = function(nums) {
let b = 0;
for (let i = 0; i < nums.length; i++) {
if(i === nums.length-b){
break;
}
if (nums[i] === 0) {
nums.splice(i, 1);
nums.push(0);
b++;
i--
}
}
};
解法二
思路:双指针法,解法一中有提到,在for循环中遍历时删除数组元素是一种不安全的操作(JavaScript中是否属于安全操作?待思考~),那么,可以将解法进行优化,使用双指针比较来代替数组遍历次数。实现思路和解法一相同,先移除元素后push末尾
var moveZeroes = function(nums) {
const max = nums.length
let start = 0
let end = max - 1
while (start < end) {
const item = nums[start]
if (item === 0) {
nums.splice(start, 1)
nums.push(0)
end--
continue
}
start++
}
};
解法三
思路:将数组中所有的0元素全部移除,然后根据移除数量进行push操作,此法简单粗暴,元素较多时会比较消耗时间。
var moveZeroes = function(nums) {
let count =0
for (let i = 0; i < nums.length; i++) {
if (nums[i] === 0) {
nums.splice(i, 1);
i--;
count++;
}
}
for(let j = 0;j<count;j++){
nums.push(0);
}
};
此题难度较为简单,考虑细节点可能有:
- 数组删除时的索引变化
- 数组索引的移动量