数组之快慢指针

696 阅读2分钟

主要思想

实现步骤:从同一起点出发,当碰到某一条件的时候,快指针继续走,慢指针不动,知道满足另外一个条件时,快指针对慢指针所处的位置值进行赋值。

实现思想:快指针和慢指针因为某些条件走的次数或者理解成它们的速度不同,可以利用慢指针满足条件后的执行,让时间复杂度减少,这样的话就不需要每个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

}`