[Go版]算法通关村第三关白银——双指针的妙用

本文介绍了双指针算法的两种主要类型——快慢指针和左右指针,以及它们在解决数组和链表问题中的应用。通过示例题目和Go代码展示了如何运用这两种方法实现不同功能,如移除元素、删除有序数组中的重复项、轮转数组等,同时分析了时间复杂度和空间复杂度。

双指针算法思想

双指针是一种常用的算法思想,通常用于在数组或链表等数据结构中解决一些问题。双指针技巧通过使用两个指针来遍历数据结构,从而在一次遍历中解决问题,避免使用额外的数据结构,从而降低时间复杂度和空间复杂度。

常见的两种类型:快慢指针和左右指针。

快慢指针

快慢指针一般用于解决链表相关的问题。快指针每次移动两步,慢指针每次移动一步。通过快慢指针的遍历,可以找到链表的中间节点、判断链表是否有环、寻找链表倒数第 k 个节点等问题。

左右指针

左右指针一般用于解决数组或字符串相关的问题。左指针从数组的最左边开始,右指针从数组的最右边开始,然后向中间移动。通过左右指针的遍历,可以找到满足某种条件的子数组或子字符串,比如两数之和、反转数组、滑动窗口等问题。

双指针应用实例

题目:移除元素

题目链接:LeetCode-27. 移除元素
在这里插入图片描述

方法一:左右指针+交换值(图解如下)

在这里插入图片描述

复杂度:时间复杂度: O ( n ) O(n) O(n)、空间复杂度: O ( 1 ) O(1) O(1)
  • 时间复杂度: O ( n ) O(n) O(n)

该函数使用了双指针技巧来移除数组中等于给定值 val 的元素。双指针方法可以将数组中所有等于 val 的元素移动到数组的末尾,并返回新数组的长度。
在最坏情况下,如果数组中所有元素都等于 val,那么需要遍历整个数组,时间复杂度是 O ( n ) O(n) O(n),其中 n 是数组的长度。

  • 空间复杂度: O ( 1 ) O(1) O(1)

该函数只使用了常量级别的额外空间来存储变量和常数。没有使用与输入规模成比例的额外数据结构。因此,空间复杂度是 O ( 1 ) O(1) O(1)

Go代码
func removeElement(nums []int, val int) int {
   
   
    length := len(nums)
    left, right := 0, length-1
    for left<=right {
   
   
        if nums[left]==val && nums[right]!= val {
   
   
            nums[left], nums[right] = nums[right], nums[left]
            left++
            right--
        }
        if nums[left] != val {
   
   
            left++
        }
        if nums[right] == val {
   
   
            right--
        }
    }
    return left
}

方法二:快慢指针+覆盖值(图解如下)

fast指针用于遍历数组,slow指针用于标记新数组的边界。当fast指针找到一个不等于val的元素时,将其复制到slow指针所在的位置,并递增slow指针。这样,slow指针之前的元素就构成了新数组。
在这里插入图片描述

复杂度:时间复杂度: O ( n ) O(n) O(n)、空间复杂度: O ( 1 ) O(1) O(1)
Go代码
func removeElement(nums []int, val int) int {
   
   
    length := len(nums)
    slow, fast := 0, 0
    for ; fast<length; fast++ {
   
   
        if nums[fast] != val {
   
   
            nums[slow] = nums[fast]
            slow++
        }
    }
    return slow
}

题目:删除有序数组中的重复项

题目链接:LeetCode-26. 删除有序数组中的重复项
在这里插入图片描述

方法:快慢指针+覆盖值

复杂度:时间复杂度: O ( n ) O(n) O(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值