27-移除元素
快慢指针
这里的快慢指针其实就是数组的索引,只不过一个索引走的慢、一个索引走的快,对于一个长度为 n的数组来说,[0, slow-1]是符合某条件的处理区域,[slow, fast-1]是不符合某条件的已处理区域,[fast, n-1]是未处理区域。
一般来说,当满足某条件,快慢指针同时移动,不满足某条件时,只有快指针移动。
// 快慢指针模版
function template(nums) {
let n = nums.length
let slow = 0, fast = 0
while(fast < n) {
// 满足某个条件时 慢指针、快指针都移动
if (true) {
slow++
}
// 不满足时,只有快指针移动
fast++
}
}
这里我们使用快慢指针的方式解决本问题。数组可以被分为以下区域
● [0, slow - 1]
是不等于 val的区域
● [slow, fast -1]
是等于 val要删除的区域
● [fast, n-1]
是未处理区域
当 fast >= n
时,数组已经被处理完毕,此时数组已经被分成两部分,[0, slow - 1]
是不等于 val的区域,[slow, n - 1]
是等于 val的区域,想要返回不等于 val
区域的长度,直接返回 slow
即可。
var removeElement = function(nums, val) {
if(nums.length == 0) return 0
let slow = 0
let fast = 0
while(fast < nums.length) {
if(nums[fast] !== val) {
nums[slow] = nums[fast]
slow++
}
fast++
}
return slow
};
对撞指针
如果要删除的元素特别少,怎样可以提高性能呢?
[3,2,2,3,2,3,1] val = 1
[1,2,2,3,2,3,3] val = 1 // 多次重新赋值
left指向的元素需要删除时,right指针指向的元素赋予到left,right–
当left小于right时,退出循环
var removeElement = function(nums, val) {
if(nums.length == 0) return 0
let left = 0
let right = nums.length - 1
// 解法产生的bug,如果末尾也是要删除的元素,则替换到开头去了
while(left <= right) {
// 遇到要删除的元素,我们使用数组最后一个元素来替换这个元素
// 替换后的数字有可能也是要删除的元素,那就接着判断
// 但是至少,我们从数组的最后删除了一个元素
if(nums[left] === val) {
nums[left] = nums[right]
right--
}
// 原因出在这里,只有nums[left] !== val的时候,left++
else {
left++
}
// left++
}
return right + 1
};