返回

去粗存精,事半功倍——双指针算法 LeetCode 解题精要

闲谈

双指针算法的奥秘在于,它使用两个指针变量在数组或链表中移动,通过比较和操作指针指向的元素,来有效地解决各种问题。双指针算法通常用于解决以下几类问题:

  • 查找两个有序数组或链表中的中位数
  • 合并两个有序数组或链表
  • 寻找数组或链表中的最长连续子序列
  • 寻找数组或链表中的最长回文子串
  • 寻找数组或链表中的最长递增子序列

在 LeetCode 中,双指针算法的应用场景非常广泛,包括但不限于:

  • 两数之和:给定一个整数数组和一个目标值,找出数组中两个元素之和等于目标值的索引。
  • 盛最多水的容器:给定一个非负整数数组,表示容器的宽度,找出两个容器可以容纳最多的水。
  • 最长回文子串:给定一个字符串,找出最长的回文子串。
  • 最长递增子序列:给定一个整数数组,找出最长的递增子序列。

下面,我们以 LeetCode 上的经典问题「合并两个有序数组」为例,详细解析双指针算法的具体实现过程:

def merge(nums1, m, nums2, n):
    """
    :type nums1: List[int]
    :type m: int
    :type nums2: List[int]
    :type n: int
    :rtype: None
    """
    # 定义两个指针变量,分别指向nums1和nums2的尾部
    p1 = m - 1
    p2 = n - 1
    # 从nums1和nums2的尾部开始比较和合并元素
    while p1 >= 0 and p2 >= 0:
        if nums1[p1] >= nums2[p2]:
            nums1[p1 + p2 + 1] = nums1[p1]
            p1 -= 1
        else:
            nums1[p1 + p2 + 1] = nums2[p2]
            p2 -= 1
    # 将nums2中剩余的元素复制到nums1中
    while p2 >= 0:
        nums1[p1 + p2 + 1] = nums2[p2]
        p2 -= 1

在上述代码中,我们使用两个指针变量 p1 和 p2 分别指向 nums1 和 nums2 的尾部,然后从尾部开始比较和合并元素。如果 nums1 中的元素大于或等于 nums2 中的元素,则将 nums1 中的元素复制到 nums1 和 nums2 合并后的数组的末尾,并向左移动 p1 指针。否则,将 nums2 中的元素复制到 nums1 和 nums2 合并后的数组的末尾,并向左移动 p2 指针。重复这个过程,直到 nums1 和 nums2 中的所有元素都被合并完毕。

通过双指针算法,我们可以在时间复杂度为 O(m + n) 的情况下,将两个有序数组合并成一个有序数组。这种算法不仅简洁高效,而且很容易理解和实现,因此非常适合在 LeetCode 中解决各种算法挑战。

当然,双指针算法的应用场景远不止于此。通过不断地练习和探索,你将发现双指针算法的强大之处,并在 LeetCode 中取得更加出色的成绩。