AI刷题中的双指针 | 豆包MarsCode AI刷题

65 阅读3分钟

AI刷题中的链表

在AI刷题中,有许多链双指针的题,这篇文章结合题目来讲一下双指针的知识点和python中的应用。

一、双指针概念

双指针是一种非常高效的算法思想,常用于数组或链表等线性结构中,通过两个指针在数据结构上以某种策略移动,从而减少时间复杂度。

双指针分为以下几种常见类型:

  1. 快慢指针:用于检测链表中的环、寻找中间节点等。
  2. 对撞指针:用于解决排序数组中的两数之和、回文检测等问题。
  3. 滑动窗口:用于解决子数组、子字符串相关的问题(如最长子序列、最小覆盖子串等)。

1.快慢指针示例

问题:链表环检测

给定一个链表,判断链表中是否存在环。

class ListNode: 
    def __init__(self, val=0, next=None):
        self.val = val 
        self.next = next 
    def hasCycle(head): 
        slow = fast = head 
        while fast and fast.next: 
        # 快指针可以继续走两步 
            slow = slow.next # 慢指针走一步 
            fast = fast.next.next # 快指针走两步 
            if slow == fast: # 快慢指针相遇,存在环 
                return True 
        return False

在这段代码中,时间和空间复杂度分别为:

  • 时间复杂度:O(n),每个节点最多被访问两次。
  • 空间复杂度:O(1),只使用两个指针。

2. 对撞指针示例

问题:排序数组中的两数之和
在一个升序数组中找到两个数,使得它们的和为目标值。

def twoSum(numbers, target): 
    left, right = 0, len(numbers) - 1 # 初始化左右指针         
    while left < right: 
        current_sum = numbers[left] + numbers[right] 
        if current_sum == target: 
            return [left + 1, right + 1] # 返回索引(从1开始) 
        elif current_sum < target: 
            left += 1 # 当前和小于目标值,左指针右移 
        else: 
            right -= 1 # 当前和大于目标值,右指针左移         
        return []

在这段代码中,时间和空间复杂度分别为:

  • 时间复杂度:O(n),左右指针各遍历一次。

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

3.滑动窗口示例**

问题:找到字符串中的最长无重复子串
给定一个字符串,找到最长的无重复字符子串的长度。

代码实现

def lengthOfLongestSubstring(s):
    char_set = set()
    left = 0
    max_length = 0

    for right in range(len(s)):
        while s[right] in char_set:  # 如果遇到重复字符,缩小窗口
            char_set.remove(s[left])
            left += 1
        char_set.add(s[right])  # 加入新字符
        max_length = max(max_length, right - left + 1)  # 更新最大长度

    return max_length

滑动窗口是一种动态调整范围的双指针方法,窗口右边界扩展时记录结果,左边界缩小时删除无效元素。

  • 时间复杂度:O(n),每个字符最多被访问两次。

  • 空间复杂度:O(min(n, m)),m 是字符集大小。

二、双指针的通用思路

  1. 初始化指针:确定两个指针的初始位置,通常是 left = 0right = n-1

  2. 移动条件:根据问题特点,决定如何移动指针,例如:

    • 比较两数和,移动靠近目标的指针。
    • 碰到重复元素时,缩小窗口。
  3. 边界条件:防止指针越界或进入死循环。

三、总结

  1. 双指针的核心在于减少不必要的遍历,提升效率。
  2. 根据问题特点选择适合的双指针策略(快慢、对撞、滑动窗口)。
  3. 配合排序或哈希表等其他技术,可以解决更复杂的问题。