【LeetCode 热题 100】11. 盛最多水的容器——Java双指针解法

11. 盛最多水的容器

整体思路

这段代码采用了双指针(Two-Pointers) 的优化算法来解决"盛最多水的容器"问题。与暴力枚举所有可能性的 O(n²) 方法不同,双指针法通过一种更智能的收缩策略,仅需一次遍历即可找到最大面积,效率极高。

其整体思路如下:

  1. 初始化指针 :算法设置两个指针,left 指向数组的第一个元素(索引 0),right 指向数组的最后一个元素(索引 n-1)。这两个指针代表了当前考虑的容器的左右两个边界。这个初始状态构成了宽度最大的容器。

  2. 迭代收缩 :指针 left 和 right 在一个 while 循环中相向移动,直到它们相遇(left >= right)。在每次循环中,执行以下操作:

    • 计算当前面积 :容器的宽度是 w = right - left,高度 h 则由两个边界中较短的那条线决定,即 h = Math.min(height[left], height[right])。当前容器的面积就是 area = w * h。
    • 更新最大面积 :将当前计算出的 area 与全局最大面积 ans 进行比较,并始终保留较大者。
  3. 指针移动策略(核心) :这是算法的关键所在。在计算完当前面积后,需要决定移动哪个指针(left 还是 right)来寻找下一个可能的更大容器。

    • 当前面积受限于宽度 和高度 。由于指针在相向移动,宽度 w 在后续的迭代中只会减小,不会增大。
    • 因此,要想找到一个更大的面积,唯一的希望就是增加容器的高度 h。
    • 容器的高度 h 由 height[left] 和 height[right] 中的短板决定。如果移动长板那一侧的指针,短板依然是那个短板,高度 h 不会增加(甚至可能减小),而宽度 w 又减小了,所以面积必然不会变大。
    • 结论是:必须移动指向短板的那个指针。因为只有移动短板,才有可能在下一次迭代中遇到一个更高的板,从而增加容器的整体高度,弥补宽度减小的损失,进而才有可能找到更大的面积。
  4. 返回结果 :当 while 循环结束时(left 和 right 相遇),意味着所有具有潜力的容器都已被考虑过。此时 ans 中存储的就是最终的最大面积。

完整代码

java 复制代码
class Solution {
    public int maxArea(int[] height) {
        // ans 用于存储并更新找到的最大面积,初始化为0。
        int ans = 0;
        // 初始化左指针,指向数组的起始位置。
        int left = 0;
        // 初始化右指针,指向数组的末尾位置。
        int right = height.length - 1;

        // 当左指针在右指针左侧时,持续循环。
        // 这是双指针算法的核心循环结构。
        while (left < right) {
            // 计算当前容器的宽度,即两个指针之间的距离。
            int w = right - left;
            // 计算当前容器的高度,由左右两条线中较短的一条决定。
            int h = Math.min(height[left], height[right]);
            // 计算当前容器的面积。
            int area = w * h;
            // 将当前面积与已知的最大面积比较,并更新最大面积。
            ans = Math.max(ans, area);

            // --- 核心移动逻辑 ---
            // 如果左边的线比右边的线短。
            if (height[left] < height[right]) {
                // 移动左指针向右。因为移动短板才有可能找到更高的板,从而可能获得更大的面积。
                left++;
            } else {
                // 如果右边的线比左边的线短,或者两者一样高。
                // 移动右指针向左。
                right--;
            }
        }
        
        // 循环结束后,ans 中保存的就是最终的最大面积。
        return ans;
    }
}

时空复杂度

时间复杂度:O(n)
  1. 分析依据 :算法使用 left 和 right 两个指针。left 从 0 开始向右移动,right 从 n-1 开始向左移动。
  2. 在 while 循环的每一次迭代中,要么 left 加一,要么 right 减一,两个指针之间的距离 right - left 至少会减少1。
  3. 两个指针只会相向移动,绝不会后退或停滞。它们从数组的两端开始,直到相遇为止。
  4. 因此,两个指针总共会移动 n-1 步。这意味着循环体内的操作最多执行 n-1 次。

结论 :算法的执行时间与输入数组的规模 n 呈线性关系,因此时间复杂度为 O(n)。

空间复杂度:O(1)
  1. 分析依据 :算法在执行过程中,除了输入数组 height 本身占用的空间外,只使用了有限几个变量(ans, left, right, w, h, area)。
  2. 这些变量的数量是固定的,不随输入数组 height 的大小 n 的增加而增加。
  3. 没有创建任何新的、大小与 n 相关的辅助数据结构(如额外的数组、哈希表等)。

结论 :算法所需的额外存储空间是常数级别的,因此空间复杂度为 O(1)。

相关推荐
the3clipse2 分钟前
H.265熵编码核心:CABAC自适应二进制算术编码详解——如何将语法元素高效压缩为比特流
人工智能·算法·视频编码·h.265·hevc·cabac·cavlc
海绵宝宝转agent4 分钟前
LeetCode100 LRU缓存思路讲解
java·开发语言·缓存
CQU_JIAKE4 分钟前
10.4【A】
算法
专业程序开发源4 分钟前
springboot高校学生社团管理系统74810-计算机课程设计、毕业设计
java·vue.js·spring boot·后端·spring·php·课程设计
youdexiang10 分钟前
AI 生成会议纪要好用吗?多款 APP 功能分析
java·人工智能·音视频
Godspeed Zhao20 分钟前
现代智能雷达技术19——算法(5)
算法
(Charon)22 分钟前
【C++面试】RAII到底是什么:从资源管理理解C++对象生命周期
c++·算法·面试
Omics Pro30 分钟前
之江实验室NAR|虚拟细胞3阶段训练范式
数据库·人工智能·算法·机器学习·自然语言处理
通信瓦工31 分钟前
OCP 冷却环境与冷却剂分配单元(CDU)子项目
java·开发语言
Tisfy36 分钟前
LeetCode 0678.有效的括号字符串:O(n)+O(1)一次遍历
算法·leetcode·字符串·题解·贪心·括号匹配