跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

双指针经典算法题实战解析:从原理到代码

双指针算法通过两个指针的相对运动优化数组遍历效率。本文涵盖移动零、复写零、快乐数、容器盛水、有效三角形及多数之和等经典题型。重点解析了如何利用单调性降低时间复杂度至 O(N),以及三数之和中去重与边界处理的细节。通过代码示例展示快慢指针检测环、对撞指针收缩区间等核心技巧,帮助读者理解算法本质而非单纯记忆模板。

奇形怪状发布于 2026/3/27更新于 2026/6/1120 浏览
双指针经典算法题实战解析:从原理到代码

双指针经典算法题实战解析

双指针是处理数组和链表问题的高效技巧,核心在于利用两个指针的相对运动来减少时间复杂度。下面结合几道经典题目,聊聊其中的设计思路与边界细节。

1. 移动零 (Move Zeroes)

题目链接: LeetCode 283

这道题的目标是将数组中的 0 移动到末尾,同时保持非零元素的相对顺序。最直观的思路是用双指针将数组划分为三个区间:已处理的非零区、待处理的零区、未处理区。

我们可以维护一个 dest 指针指向非零区的末尾,初始为 -1;cur 指针遍历数组。当 cur 遇到非零元素时,先扩展非零区(++dest),再交换 dest 和 cur 的值。如果 cur 遇到 0,则直接跳过,让它留在零区。

def moveZeroes(nums):
    dest = -1
    for cur in range(len(nums)):
        if nums[cur] != 0:
            dest += 1
            nums[dest], nums[cur] = nums[cur], nums[dest]

注意,循环结束时 cur 会遍历完整个数组,此时所有非零元素都已按序前移,剩余位置自然填充为 0。

2. 复写零 (Duplicate Zeros)

题目链接: LeetCode 1089

如果直接从前往后模拟复写 0,后面的数据会被覆盖。因此,更稳妥的策略是从后往前操作。

我们需要先确定最后一个需要复写的数字位置。可以设 cur 从头开始,dest 从逻辑上的末尾开始(考虑复写后的长度)。当 cur 遇到 0 时,dest 走两步并标记为 0;遇到非 0 时,dest 走一步复制值。

这里有个关键点:dest 可能会走到原数组范围之外,这通常意味着最后一个 0 被截断了,需要单独处理边界情况。实际编码时,建议先计算有效长度,再倒序填充。

3. 快乐数 (Happy Number)

题目链接: LeetCode 202

判断一个数是否为快乐数,本质上是检测数字变换过程中是否存在环。无论结果是 1 还是进入死循环,最终都会形成闭环。

使用快慢指针法:定义一个函数计算数字各位平方和。快指针每次运算两次,慢指针每次运算一次。如果存在环,两者必会相遇。相遇时若值为 1,则是快乐数;否则不是。

def get_next(n):
    total_sum = 0
    while n > 0:
        n, digit = divmod(n, 10)
        total_sum += digit ** 2
    return total_sum

def isHappy(n):
    slow = n
    fast = get_next(n)
    while fast != 1 and slow != fast:
        slow = get_next(slow)
        fast = get_next(get_next(fast))
    return fast == 1

注意初始化时不要让两指针相等,否则无法进入循环检测。

4. 盛最多水的容器 (Container With Most Water)

题目链接: LeetCode 11

暴力枚举需要 O(N²),利用单调性可以将复杂度降为 O(N)。核心思想是对撞双指针:左右指针分别指向数组首尾。

面积由较短边决定。如果固定短边向内移动,高度不可能增加,面积只会减小或不变。因此,我们总是移动高度较小的那个指针,试图寻找更高的边来扩大面积。这样只需遍历一次即可找到最大值。

5. 有效三角形的个数 (Valid Triangle Number)

题目链接: LeetCode 611

构成三角形的条件是任意两边之和大于第三边。若数组已排序(a ≤ b ≤ c),只需验证 a + b > c 即可。

优化策略是先排序,然后固定最大边 c,用双指针 left 和 right 在剩余部分查找满足条件的组合。若 nums[left] + nums[right] > nums[c],说明 left 到 right-1 之间的所有数与 right 都能组成三角形,直接累加计数,然后 right--;否则 left++。

6. 两数之和 II (Two Sum II)

题目链接: LeetCode 167

输入数组已排序,直接使用对撞双指针。左指针指向头,右指针指向尾,根据当前和与目标值的比较移动指针:和大则右移左指针,和小则右移右指针,相等则返回结果。时间复杂度 O(N)。

7. 三数之和 (3Sum)

题目链接: LeetCode 15

这是双指针的经典进阶应用。外层循环固定一个数 i,内层使用双指针寻找另外两个数。难点在于去重和边界处理。

  1. 去重: 如果 nums[i] 与前一个相同,跳过;找到一组解后,left 和 right 也要跳过重复值,避免重复三元组。
  2. 边界: 确保 left < right,防止越界。
def threeSum(nums):
    nums.sort()
    res = []
    for i in range(len(nums)):
        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:
                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
            elif s < 0: left += 1
            else: right -= 1
    return res

8. 四数之和 (4Sum)

题目链接: LeetCode 18

在三数之和的基础上多套一层循环。同样需要注意去重逻辑和溢出问题。由于四个数相加可能超出整型范围,求和时需强转为长整型(如 C++ 中的 long long)。


以上这些题目展示了双指针在不同场景下的变体:同向移动、对撞移动、快慢指针等。掌握其背后的单调性与空间划分思想,比死记硬背代码更重要。

目录

  1. 双指针经典算法题实战解析
  2. 1. 移动零 (Move Zeroes)
  3. 2. 复写零 (Duplicate Zeros)
  4. 3. 快乐数 (Happy Number)
  5. 4. 盛最多水的容器 (Container With Most Water)
  6. 5. 有效三角形的个数 (Valid Triangle Number)
  7. 6. 两数之和 II (Two Sum II)
  8. 7. 三数之和 (3Sum)
  9. 8. 四数之和 (4Sum)
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • C++ STL vector 容器源码实现详解
  • Python 入门真相:半个月学会只是幸存者偏差
  • C++ 搜索引擎 Searcher 模块:正倒排索引与 Boost 实现
  • Spring Boot 数据导入导出与报表生成实战
  • Python 学习需要多长时间?
  • JavaScript 窗口、文档及表单对象操作示例
  • 微信集成 Qclaw AI 智能体:零门槛操作指南
  • GitHub Pages 零代码搭建免费网站实战指南
  • 本地部署 Z-Image-Turbo:16GB 显存实现高效 AI 绘画
  • Windows 系统升级 Node.js 版本完整教程
  • VRCX 技术实现解析:VRChat 社交管理架构
  • 系统架构设计效率对比:AI 辅助与传统方法实践
  • 利用提示词优化 AI 生成内容,去除机器写作痕迹
  • 贪心算法实战:从摆动序列到股票买卖
  • 网络安全从业人员必备认证证书指南
  • 自学网络安全:学习误区、路线规划与资源推荐
  • Ubuntu 22.04 升级 Node.js 版本方法
  • Web 前端基础:HTML 核心语法与常用标签
  • 2023 版 Android 面试指南,涵盖核心技能
  • 多种智能优化算法改进在线顺序极限学习机 (OSELM) 预测模型

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online