Leetcode-100 双指针

概述

双指针法通过维护两个指针高效解决数组/链表问题,主要分为:

  • 同向指针(快慢指针)
  • 相向指针(左右指针)
  • 滑动窗口(特殊双指针)

适用于处理有序数组、子数组问题,时间复杂度通常为O(n)


283.移动零

题目特征

  • 保持非零元素相对顺序
  • 原地操作(不能新建数组)
  • 最小操作次数

双指针解法

关键思想:快指针扫描非零元素,慢指针标记填充位置

算法步骤

  1. 初始化慢指针slow=0
  2. 快指针fast遍历数组:
    • 当nums[fast]非零时,与nums[slow]交换
    • slow前进
  3. 遍历结束后,slow之后的位置置零(可优化为直接覆盖)

示例说明
输入:[0,1,0,3,12]
过程演示:
fast=0(0跳过) → fast=1(1交换到0位) → fast=2(0跳过) →
fast=3(3交换到1位) → fast=4(12交换到2位)
最终结果:[1,3,12,0,0]

复杂度分析

  • 时间复杂度:O(n)
  • 空间复杂度:O(1)
def moveZeroes(nums):
    slow = 0
    for fast in range(len(nums)):
        if nums[fast] != 0:
            nums[slow], nums[fast] = nums[fast], nums[slow]
            slow += 1

11.盛水最多的容器

题目特征

  • 寻找最大矩形面积

  • 高度由短板决定

  • 需要高效扫描方法

双指针解法

关键思想:从两端向中间收敛,每次移动较矮的边

算法步骤:
1.初始化left=0, right=len(height)-1
2.计算当前面积并更新最大值
3.移动高度较小的一侧指针
4.重复直到指针相遇

正确性证明:
移动较高边:宽度减小,高度不会超过原短板,面积必然减小
移动较低边:可能获得更高短板,存在更大面积的可能性

复杂度分析:

  • 时间复杂度:O(n)

  • 空间复杂度:O(1)

def maxArea(height):
    left, right = 0, len(height)-1
    max_water = 0
    while left < right:
        h = min(height[left], height[right])
        max_water = max(max_water, h*(right-left))
        if height[left] < height[right]:
            left += 1
        else:
            right -= 1
    return max_water

15.三数之和

题目特征

  • 需要去重
  • 组合问题
  • 时间复杂度优化要求

排序+双指针

解题框架

  1. 数组排序(O(nlogn))
  2. 遍历固定第一个数nums[i]
  3. 在i+1到末尾区间使用双指针找两数之和为-nums[i]

去重策略:

  1. 当nums[i] == nums[i-1]时跳过(i>0)
  2. 找到解后,跳过left右侧相同值
  3. 找到解后,跳过right左侧相同值

示例说明
输入:[-1,0,1,2,-1,-4]
过程演示:
排序后:[-4,-1,-1,0,1,2]
i=0时,在[-1,-1,0,1,2]中找两数之和为4

复杂度分析

  • 时间复杂度:O(n)
  • 空间复杂度:O(1)
def threeSum(nums):
    nums.sort()
    res = []
    for i in range(len(nums)-2):
        if i>0 and nums[i]==nums[i-1]:
            continue
        left, right = i+1, len(nums)-1
        while left < right:
            s = nums[i]+nums[left]+nums[right]
            if s < 0:
                left +=1
            elif s >0:
                right -=1
            else:
                res.append([nums[i],nums[left],nums[right]])
                while left<right and nums[left]==nums[left+1]:
                    left +=1
                while left<right and nums[right]==nums[right-1]:
                    right -=1
                left +=1
                right -=1
    return res

42.接雨水

题目特征

  • 立体图形计算
  • 需要考虑左右边界
  • 多种解法比较(动态规划、单调栈、双指针

双指针优化解法

核心思路:维护左右最大高度,每次处理较小的一侧

算法步骤

  1. 初始化left=0, right=len(height)-1
  2. 维护left_max和right_max
  3. 比较height[left]和height[right]:
    • 左较小:计算左指针处水量,移动左指针
    • 右较小:计算右指针处水量,移动右指针

正确性解释:
当height[left] < height[right]时,left_max是可信的短板
水量由left_max - height[left]决定

复杂度分析

  • 时间复杂度:O(n)
  • 空间复杂度:O(1)
def trap(height):
    left, right = 0, len(height)-1
    left_max = right_max = water = 0
    while left < right:
        if height[left] < height[right]:
            left_max = max(left_max, height[left])
            water += left_max - height[left]
            left +=1
        else:
            right_max = max(right_max, height[right])
            water += right_max - height[right]
            right -=1
    return water

总结与题型特征

双指针适用场景
题型特征指针类型
元素移动保持顺序,原地操作快慢指针
有序数组组合需要避免暴力枚举相向指针
容器类问题面积/容量计算相向指针
多条件约束问题需要同时满足多个条件多指针组合
解题技巧
  • 先尝试排序(需要考虑时间复杂度)
  • 画图辅助理解
  • 注意去重条件以及边界处理
  • 分析指针移动的单调性
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值