双指针 | 豆包MarsCode AI刷题

111 阅读2分钟

常见的双指针解题思路有以下几种:

1. 固定一个指针,移动另一个指针

  • 常用于求解数组或链表中的某种特定条件,比如两个元素的和等于某个目标值。
  • 例如,在有序数组中求两个数的和为目标值,可以让一个指针指向数组的开始位置,另一个指针指向数组的末尾位置,然后根据和的大小调整指针。

例子

def twoSum(nums, target):
    left, right = 0, len(nums) - 1
    while left < right:
        current_sum = nums[left] + nums[right]
        if current_sum == target:
            return [left, right]
        elif current_sum < target:
            left += 1
        else:
            right -= 1
    return None

时间复杂度:O(n)

2. 左右指针同时移动

  • 有时需要通过两个指针来同时扫描某个结构,解题时两指针会一起向前推进,直到满足某个条件。
  • 这种方法常常用于删除数组中的重复元素或归并两个有序数组。

例子:删除排序数组中的重复元素

def removeDuplicates(nums):
    if not nums:
        return 0
    slow = 0
    for fast in range(1, len(nums)):
        if nums[fast] != nums[slow]:
            slow += 1
            nums[slow] = nums[fast]
    return slow + 1

时间复杂度:O(n)

3. 快慢指针

  • 快慢指针是一种特别的双指针技巧,其中一个指针以两倍速前进,另一个指针以常规速度前进。这种技巧常用于链表中的循环检测或找链表的中间节点等问题。
  • 通过这种方法,可以在一个链表中有效地找到环的入口点或检测是否存在环。

例子:链表的环检测

def hasCycle(head):
    slow, fast = head, head
    while fast and fast.next:
        slow = slow.next
        fast = fast.next.next
        if slow == fast:
            return True
    return False

时间复杂度:O(n)

4. 滑动窗口

  • 滑动窗口的基本思想是使用两个指针(左指针和右指针),通过调整窗口大小来满足某种条件。
  • 它通常用于处理数组或字符串的子串问题,比如最长不重复子串、子数组和等问题。

例子:最长无重复字符子串

def lengthOfLongestSubstring(s):
    char_map = {}
    left = 0
    max_len = 0
    for right in range(len(s)):
        if s[right] in char_map and char_map[s[right]] >= left:
            left = char_map[s[right]] + 1
        char_map[s[right]] = right
        max_len = max(max_len, right - left + 1)
    return max_len

时间复杂度:O(n)

5. 双指针与递归结合

  • 双指针方法也可以和递归结合起来使用,特别是处理分治类问题时。

例子:归并排序中的双指针

def merge(left, right):
    result = []
    i, j = 0, 0
    while i < len(left) and j < len(right):
        if left[i] < right[j]:
            result.append(left[i])
            i += 1
        else:
            result.append(right[j])
            j += 1
    result.extend(left[i:])
    result.extend(right[j:])
    return result

总结

  • 双指针的优势:可以在很多情况下减少暴力破解的复杂度,通常能够将时间复杂度降低至 O(n)。
  • 适用场景:排序数组、链表、字符串等数据结构中,尤其是当问题涉及查找、比较、合并、去重时。