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

11. 盛最多水的容器

整体思路

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

其整体思路如下:

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

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

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

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

相关推荐
崎岖Qiu3 分钟前
【Spring篇08】:理解自动装配,从spring.factories到.imports剖析
java·spring boot·后端·spring·面试·java-ee
belldeep10 分钟前
java:如何用 JDBC 连接 TDSQL 数据库
java·数据库·jdbc·tdsql
2301_1472583691 小时前
7月2日作业
java·linux·服务器
香饽饽~、1 小时前
【第十一篇】SpringBoot缓存技术
java·开发语言·spring boot·后端·缓存·intellij-idea
小莫分享1 小时前
移除 Java 列表中的所有空值
java
2301_803554523 小时前
c++中类的前置声明
java·开发语言·c++
hn小菜鸡6 小时前
LeetCode 377.组合总和IV
数据结构·算法·leetcode
不想写bug呀6 小时前
多线程案例——单例模式
java·开发语言·单例模式
Deepoch6 小时前
Deepoc 大模型:无人机行业的智能变革引擎
人工智能·科技·算法·ai·动态规划·无人机
心平愈三千疾7 小时前
通俗理解JVM细节-面试篇
java·jvm·数据库·面试