主要思想
实现步骤:从同一起点出发,当碰到某一条件的时候,快指针继续走,慢指针不动,知道满足另外一个条件时,快指针对慢指针所处的位置值进行赋值。
实现思想:快指针和慢指针因为某些条件走的次数或者理解成它们的速度不同,可以利用慢指针满足条件后的执行,让时间复杂度减少,这样的话就不需要每个i循环遍历j(j可能会执行len次),这样的话就会减少时间复杂度
实例及实现
示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。
示例 2: 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。
注意点:主要是因为数组删除除了用splice,只能覆盖,前面的值被删除之后,需要后面的值进行覆盖,遍历前面的i值需要O(n),用后面的j值覆盖前面的值,则也需要时间复杂度O(n),所以是O(n^2)
`1.用双层for循环,一层遍历,一层移动位置
function removTarget(nums,val){
if(nums.length<0) return
for(let i = 0;i<nums.length;i++){
if(nums[i] == val){
//将数组往左边移动 所以是一个循环
for(let j = i;j<nums.length-1;j++){
nums[j] = nums[j+1]
}
//左移后,右边位的值不变,所以需要将数组变小,更改为nums.length-1
//而因为下一次又要循环了,变成i为1了,但是数组左移了,所以需要i-1
//但是一定要是在if语句中,因为只有满足if语句后才会左移
i = i-1
nums.length = nums.length -1
}
}
return nums
}`
`2.第二种方式,用一层for循环,找到就在原数组中splice掉
function removTarget(nums,val){
if(nums.length<0) return
for(let i = 0;i<nums.length;i++){
if(nums[i] == val){
//直接用splice删除,并且数组长度会发生改变
nums.splice(i,1)
//i要回到修改后的前一个,所以要-1
i = i-1
}
}
return nums
}`
`3.第三种方式,快慢指针
思路是:快慢指针一起跑,遇到相等的时候,慢指针停下,快指针继续跑
一直跑到快指针不相等的时候,这个时候赋值,结束后,再一起跑,最后做一个收尾工作
function removTarget(nums,val){
if(nums.length<0) return
let slow = 0
for(var quick = 0;quick<nums.length;quick++){
//如果相等,quick就一直右移
//如果不相等,就把quick的值给slow,之后再slow右移
//注意一定是quick和val比较,因为quick是跑得快的那个
if(nums[quick] !== val){
nums[slow] = nums[quick]
slow++
}
}
//注意这里是quick-slow,因为quick也改变了,slow也指向了下一个
let deleteLen = quick-slow
nums.splice(slow,deleteLen)
return nums
}`