盛最多水的容器:双指针法的巧妙运用(leetcode 11)

问题描述

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

我的思考历程

最初看到这个问题,我直觉上想到的是双指针法。设置左右两个指针,分别指向数组的开头和结尾,然后逐步向中间移动。但关键问题是:应该移动哪个指针?

第一次尝试:移动较高的指针

我最初的思路是:"让高的柱子先走,因为它可能找到更高的搭档"。于是写出了这样的代码:

cpp

复制代码
// 初始错误思路
if (height[left] > height[right]) {
    h = min(height[left], height[--right]);
} else {
    h = min(height[++left], height[right]);
}

但测试后发现结果不对!这让我陷入了深深的思考...

突破时刻:为什么应该移动较矮的指针?

经过1个小时的思考和数学推导,我终于明白了其中的奥秘:

数学证明

设当前状态:容量 = min(h_left, h_right) × width

如果移动较高的指针

  • 新宽度 = width - 1

  • 新高度 ≤ min(h_left, h_right)

  • ∴ 新容量 ≤ min(h_left, h_right) × (width - 1) < 原容量

如果移动较矮的指针

  • 新宽度 = width - 1

  • 新高度可能 > min(h_left, h_right)

  • ∴ 新容量可能增加!

直观理解

想象两个柱子,一个矮一个高:

  • 移动高的柱子:容器的高度上限被矮柱子限制,宽度减少,容量必然减少

  • 移动矮的柱子:虽然宽度减少,但可能找到更高的柱子,从而增加高度补偿宽度的损失

最终解决方案

cpp

复制代码
class Solution {
public:
    int maxArea(vector<int>& height) {
        int maxArea = 0;
        int left = 0;
        int right = height.size() - 1;
        
        while (left < right) {
            int currentHeight = min(height[left], height[right]);
            int currentWidth = right - left;
            maxArea = max(maxArea, currentHeight * currentWidth);
            
            // 关键 insight:移动较矮的指针
            if (height[left] < height[right]) {
                left++;
            } else {
                right--;
            }
        }
        
        return maxArea;
    }
};

算法分析

  • 时间复杂度:O(n),每个元素最多被访问一次

  • 空间复杂度:O(1),只使用常数额外空间

  • 正确性保证:每次移动都排除了不可能产生更大容量的情况

相关推荐
沪漂阿龙15 分钟前
深度剖析神经网络学习:从损失函数到SGD,手写数字识别完整实战
人工智能·神经网络·学习
x_xbx16 分钟前
LeetCode:438. 找到字符串中所有字母异位词
算法·leetcode·职场和发展
迷路爸爸18019 分钟前
Docker 入门学习笔记 06:用一个可复现的 Python 项目真正理解 Dockerfile
笔记·学习·docker
ghie909025 分钟前
基于学习的模型预测控制(LBMPC)MATLAB实现指南
开发语言·学习·matlab
Engineer邓祥浩25 分钟前
JVM学习笔记(6) 第二部分 自动内存管理 第5章节 调优案例分析与实战
jvm·笔记·学习
ysa05103027 分钟前
斐波那契上斐波那契【矩阵快速幂】
数据结构·c++·笔记·算法
倒酒小生39 分钟前
4月7日算法学习小结
linux·服务器·学习
xinzheng新政1 小时前
Javascript·深入学习基础知识2
开发语言·javascript·学习
派大星~课堂1 小时前
【力扣-94.二叉树的中序遍历】Python笔记
笔记·python·leetcode
世人万千丶1 小时前
开源鸿蒙跨平台Flutter开发:儿童数理认知与神经塑性演化引擎_突触发生与工作记忆测绘架构
学习·flutter·华为·开源·harmonyos