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

三道双指针题的常用解法

三道题都可以用双指针处理:三数之和先排序,再固定一个数,用左右指针在剩余区间里找两数之和,并在命中后跳过重复值;盛水最多的容器从两端向中间收缩,每次移动较短的一边,保留更有机会增大面积的高度;移动零则用两个指针原地交换非零元素,把零自然推到数组末尾,同时保持非零顺序不变。

静心发布于 2026/6/30更新于 2026/8/1712 浏览
三道双指针题的常用解法

三数之和

题目描述

给你一个整数数组 nums,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k,同时还满足 nums[i] + nums[j] + nums[k] == 0。请你返回所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

  • 示例 1:

输入:nums = [-1,0,1,2,-1,-4] 输出:[[-1,-1,2],[-1,0,1]] 解释: nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0。 nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0。 nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0。 不同的三元组是 [-1,0,1] 和 [-1,-1,2]。 注意,输出的顺序和三元组的顺序并不重要。

  • 示例 2:

输入:nums = [0,1,1] 输出:[] 解释:唯一可能的三元组和不为 0。

  • 示例 3:

输入:nums = [0,0,0] 输出:[[0,0,0]] 解释:唯一可能的三元组和为 0。

思路分析

这题最省事的做法还是先排序。排序之后,三数之和可以拆成'固定一个数 + 双指针找另外两个数',这样复杂度能压到 O(n^2),也比较好去重。

我这里固定的是最右边的元素 nums[n],然后在它左边用 left 和 right 做对撞。目标其实就是找两个数,让它们的和等于 -nums[n]。如果当前和太小,就把 left 往右移;太大,就把 right 往左收。找到一组后,顺手跳过重复值,不然结果会多出一堆重复三元组。

还有一点,nums[n] < 0 时可以直接停。数组已经排过序,最右边都小于 0,前面只会更小,不可能再凑出 0 了。这种剪枝不花哨,但很实用。

代码编写

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        int n = nums.size() - 1;
        vector<vector<int>> result;
         (n >= ) {
             (nums[n] < ) {
                ;
            }
             left = , right = n - ;
             target = -nums[n];
             (left < right) {
                 (nums[left] + nums[right] > target) {
                    --right;
                }   (nums[left] + nums[right] < target) {
                    ++left;
                }  {
                    result.({nums[n], nums[left], nums[right]});
                    ++left;
                     (left < right && nums[left] == nums[left - ]) {
                        ++left;
                    }
                    --right;
                     (left < right && nums[right] == nums[right + ]) {
                        --right;
                    }
                }
            }
            --n;
             (n >=  && nums[n] == nums[n + ]) {
                --n;
            }
        }
         result;
    }
};
while
2
if
0
break
int
0
1
int
while
if
else
if
else
push_back
while
1
while
1
while
0
1
return

盛水最多的容器

题目描述

给定一个长度为 n 的整数数组 height。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i])。

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

说明:你不能倾斜容器。

  • 示例 1:

输入:[1,8,6,2,5,4,8,3,7] 输出:49 解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。

  • 示例 2:

输入:height = [1,1] 输出:1

思路分析

这题的关键不在'怎么枚举两条线',而在'怎么少做无用功'。面积公式很直接:

volume=min(height[left],height[right])*(right-left)

宽度只会随着指针移动越来越小,所以真正值得争取的是更高的短板。每一步都保留较长的那条边,移动较短的那条边,才有机会让 min(height[left], height[right]) 变大。反过来挪长边,宽度变小了,短板还没变,通常只是在原地打转。

这个思路其实挺朴素,没什么技巧味道,但对这道题正合适:两端夹住,中间收缩,边算边更新最大值。

代码编写

class Solution {
public:
    int maxArea(vector<int>& height) {
        int left = 0, right = height.size() - 1;
        int maxSize = 0;
        while (left < right) {
            int volume;
            if (height[left] < height[right]) {
                volume = height[left] * (right - left);
                ++left;
            } else {
                volume = height[right] * (right - left);
                --right;
            }
            maxSize = max(volume, maxSize);
        }
        return maxSize;
    }
};

移动零

题目描述

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意,必须在不复制数组的情况下原地对数组进行操作。

  • 示例 1:

输入:nums = [0,1,0,3,12] 输出:[1,3,12,0,0]

  • 示例 2:

输入:nums = [0] 输出:[0]

思路分析

这题还是双指针,只是角色分得更明确一点:一个指针负责找非零元素,另一个指针负责放置当前位置。遇到非零就交换,两个指针一起往前走;遇到零,右边那个指针继续扫描,左边那个指针停在原地等下一个非零补位。

这个写法的好处是原地完成,而且不会打乱非零元素的相对顺序。比起先统计再覆盖,代码短一些,也更顺手。

代码编写

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int left = 0, right = 0;
        while (left <= right && right < nums.size()) {
            if (nums[right]) {
                swap(nums[left++], nums[right++]);
            } else {
                ++right;
            }
        }
    }
};

目录

  1. 三数之和
  2. 题目描述
  3. 思路分析
  4. 代码编写
  5. 盛水最多的容器
  6. 题目描述
  7. 思路分析
  8. 代码编写
  9. 移动零
  10. 题目描述
  11. 思路分析
  12. 代码编写
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

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

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

更多推荐文章

查看全部
  • Tauri 前端配置指南:接入 Vite/Next/Nuxt/SvelteKit 等主流框架
  • 默认安全治理实践:水平越权检测与前端安全防控
  • 算法模拟:LeetCode 五道经典题解析
  • C++ 运算符重载实战:让自定义类型像内置类型一样运算
  • Spring Boot 实战:从零设计短链系统(附代码与数据库设计)
  • STL 转 STEP 转换指南:从 3D 打印到工程设计
  • 在 Cursor 中使用 MCP 服务实现自动化开发
  • 双向链表核心实现与算法实战解析
  • 黑词分析前端组件设计:双面板交互与进度监控
  • Spring Boot + jQuery 前后端分离图书管理系统:接口设计与调试
  • 前缀和算法实战:和为 K 的子数组与和可被 K 整除的子数组
  • Python 职场进阶指南:从入门到数据分析与自动化实战
  • 使用 Go 构建命令行 AI 对话客户端实战
  • Unreal Engine 5 C++插件开发实战:从零实现高性能插件模块底层架构
  • Qwen3-32B 本地部署:Clawdbot 网关与企业微信/钉钉集成实战
  • SpringBoot 住院管理系统的功能拆解与实现
  • Cesium 无人机智能航线规划:航点动作组与 AI 识别实战
  • LeetCode 2612 最少翻转次数:BFS 与有序集合的解法
  • 神的泪水-构建与解析:基于多AI模型并行的内容生成与对比分析工作流
  • 基于 AI 智能体的费曼学习法知识助手实战

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如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