【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)

相关推荐
cccc来财15 分钟前
Java实现大根堆与小根堆详解
数据结构·算法·leetcode
_Aaron___17 分钟前
面向对象的三大特性---多态
java
Kiri霧23 分钟前
IntelliJ IDEA
java·ide·kotlin·intellij-idea
daixin884844 分钟前
什么是缓存雪崩?缓存击穿?缓存穿透?分别如何解决?什么是缓存预热?
java·开发语言·redis·缓存
京茶吉鹿1 小时前
"if else" 堆成山?这招让你的代码优雅起飞!
java·后端
你我约定有三1 小时前
RabbitMQ--消息丢失问题及解决
java·开发语言·分布式·后端·rabbitmq·ruby
Coovally AI模型快速验证1 小时前
数据集分享 | 智慧农业实战数据集精选
人工智能·算法·目标检测·机器学习·计算机视觉·目标跟踪·无人机
墨尘游子1 小时前
目标导向的强化学习:问题定义与 HER 算法详解—强化学习(19)
人工智能·python·算法
张北北.1 小时前
【深入底层】C++开发简历4+4技能描述6
java·开发语言·c++
Java初学者小白1 小时前
秋招Day19 - 分布式 - 分布式事务
java·分布式