LeetCode 双指针经典双题解|盛最多水的容器 + 三数之和,从入门到进阶吃透套路

目录

[11. 盛最多水的容器](#11. 盛最多水的容器)

题目描述

解题思路

满分代码

核心关键点

[15. 三数之和](#15. 三数之和)

题目描述

解题思路

满分代码

易错点详解(必看)

刷题总结

本篇带来两道力扣高频真题:入门级《盛最多水的容器》+ 进阶级《三数之和》,通俗拆解思路、详解核心逻辑、标注易错点,新手也能一遍看懂,直接收藏刷题~


11. 盛最多水的容器

题目描述

给定一个长度为 n 的整数数组 height,有 n 条垂线,第 i 条线的两个端点是 (i, 0)(i, height[i])。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。返回容器可以储存的最大水量。

解题思路

刚接触这道题,很容易想到两层 for 循环暴力枚举,遍历所有组合计算面积,但时间复杂度太高,数据量大时会直接超时。

最优解:双指针贪心算法

  1. 初始化左指针指向数组开头右指针指向数组末尾
  2. 容器面积由短板决定:面积 = 两指针间距 × 最小高度;
  3. 核心贪心规则 :每次移动高度更小的指针(只有移动短板,才有可能让容器面积变大);
  4. 遍历过程中不断更新最大面积,直到两指针相遇。

满分代码

java

运行

复制代码
class Solution {
    public int maxArea(int[] height) {
        // 边界值判断:数组为空直接返回0
        if(height == null || height.length == 0){
            return 0;
        }
        
        // 左指针起始位置,右指针指向数组末尾
        int left = 0, right = height.length - 1;
        // 记录最大盛水量
        int maxArea = 0;
        
        // 双指针遍历
        while(left < right){
            // 计算当前面积:宽度 * 最小高度
            int currentArea = (right - left) * Math.min(height[left], height[right]);
            // 更新最大面积
            maxArea = Math.max(maxArea, currentArea);
            
            // 贪心策略:移动高度较小的指针
            if(height[left] < height[right]){
                left++;
            }else{
                right--;
            }
        }
        return maxArea;
    }
}

核心关键点

  • 时间复杂度:O(n)(仅遍历一次数组)
  • 空间复杂度:O(1)(仅使用常数变量)
  • 本质:利用贪心思想,舍弃无效枚举,最大化计算效率

15. 三数之和

题目描述

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

解题思路

这道题是双指针进阶题 ,也是面试必考的去重陷阱题 ,核心难点在于排序 + 双指针 + 严格去重

  1. 先排序:对数组排序,方便后续指针移动和去重操作;
  2. 固定一个数 :遍历数组,将 nums[i] 作为第一个数(a);
  3. 双指针找另外两个数 :左指针 left = i+1(b),右指针 right = 数组末尾(c);
  4. 指针移动规则
    • 三数之和 > 0:右指针左移(减小数值);
    • 三数之和 < 0:左指针右移(增大数值);
    • 三数之和 = 0:记录结果,同时去重,移动指针;
  1. 重中之重:去重逻辑(90% 的人都在这里出错):
    • 对第一个数 a 去重:跳过重复的 nums[i]
    • b、c 去重:找到结果后,跳过连续重复的左右指针元素。

满分代码

java

运行

复制代码
class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> result = new ArrayList<>();
        // 核心第一步:数组排序,为双指针和去重做准备
        Arrays.sort(nums);
        int len = nums.length;

        // 遍历固定第一个数字 a
        for(int i = 0; i < len; i++){
            // 剪枝优化:排序后第一个数大于0,不可能凑出和为0
            if(nums[i] > 0){
                return result;
            }
            // 对 a 去重:跳过重复元素,避免结果集重复
            if(i > 0 && nums[i] == nums[i-1]){
                continue;
            }
            
            // 定义双指针:left指向i+1,right指向数组末尾
            int left = i + 1;
            int right = len - 1;
            
            // 双指针查找 b 和 c
            while(left < right){
                int sum = nums[i] + nums[left] + nums[right];
                // 三数之和过大,右指针左移
                if(sum > 0){
                    right--;
                }
                // 三数之和过小,左指针右移
                else if(sum < 0){
                    left++;
                }
                // 找到满足条件的三元组
                else{
                    // 将结果加入集合
                    result.add(Arrays.asList(nums[i], nums[left], nums[right]));
                    
                    // 对 b 去重:跳过连续重复的left
                    while(left < right && nums[left] == nums[left+1]){
                        left++;
                    }
                    // 对 c 去重:跳过连续重复的right
                    while(left < right && nums[right] == nums[right-1]){
                        right--;
                    }
                    
                    // 找到结果后,同时移动双指针
                    left++;
                    right--;
                }
            }
        }
        return result;
    }
}

易错点详解(必看)

  1. a 的去重为什么用 nums[i] == nums[i-1]****? 如果用 nums[i] == nums[i+1],会直接跳过合法的三元组,导致结果丢失;
  2. 排序的作用:不仅方便指针移动,更是去重的前提;
  3. 剪枝优化:排序后第一个数大于 0,直接终止循环,提升效率。

刷题总结

  1. 盛最多水的容器 :双指针贪心入门题,核心是移动短板,无复杂边界处理;
  2. 三数之和 :双指针进阶题,核心是排序 + 双指针 + 三层去重,吃透去重逻辑就掌握了这道题;
  3. 双指针技巧:适用于有序数组 / 需要枚举配对的场景,是优化暴力解法的首选方案。
相关推荐
B站_计算机毕业设计之家2 小时前
计算机毕业设计:汽车数据可视化与后台管理平台 Django框架 requests爬虫 可视化 车辆 数据分析 大数据 机器学习(建议收藏)✅
python·算法·机器学习·信息可视化·django·汽车·课程设计
格林威2 小时前
工业相机图像采集处理:从 RAW 数据到 AI 可读图像,堡盟相机 C#实战代码深度解析
c++·人工智能·数码相机·opencv·算法·计算机视觉·c#
lvxiangyu1111 小时前
MPPI 算法证明重构:基于无穷维泛函变分与 KL 散度的构造性推导
算法·重构·最优控制·随机最优控制
2301_8184190111 小时前
C++中的解释器模式变体
开发语言·c++·算法
ab15151711 小时前
3.25完成*23、*24、*28、*30、*33、*38、*39、*40
算法
颜酱12 小时前
回溯算法实战练习(3)
javascript·后端·算法
小王不爱笑13213 小时前
G1 GC 的核心基础:Region 模型的补充细节
java·jvm·算法
小王不爱笑13214 小时前
三色标记算法
算法
小O的算法实验室14 小时前
2026年AST SCI1区TOP,基于速度障碍法的多无人机三维避障策略,深度解析+性能实测
算法·论文复现·智能算法·智能算法改进