Skip to content

11.盛最多水的容器

给定一个长度为n的整数数组height。有n条垂线,第i条线的两个端点是(i, 0)(i, height[i])

找出其中的两条线,使得它们与x轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

说明: 你不能倾斜容器。

示例 1:

输入:[1,8,6,2,5,4,8,3,7]

输出: 49

解释: 图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。

示例 2:

输入: height = [1,1]

输出: 1

提示:

  • n==height.length
  • 2n105
  • 0height[i]104

解法一(双指针)

思路分析:

  1. 首先确定最大盛水容量有关的两个因素, 即x轴尽可能宽, height尽可能高; 且高受限于两边的最低高度;
  2. 存在两边,所以考虑使用双指针, left指向左边, right指向右边; 即容量为 area = Math.min(height[left], height[right]) * (right - left)
  3. 可以从最大宽度开始变化,即left指向起始位置, right指向末尾位置, 然后尝试变化左右指针来获取最大盛水容量;
  4. 当左指针高度(height[left]) < 右指针高度时(height[right]), 若移动右指针,在宽度本身变小的情况,高度不发生变化, 则容量肯定变小, 移动右指针没有意义; 所以此时应该移动左指针
  5. 同理, 当 height[left] > height[right]时, 移动右指针right;
  6. 在变化过程中始终保持记录最大容量area = Math.max(area, Math.min(height[left], height[right]) * (right - left));

实现代码如下:

java
class Solution {
    public int maxArea(int[] height) {
		// 最大水量
		int area = 0;
		int left = 0;
		int right = height.length - 1;
		while (left < right) {
			area = Math.max(area, Math.min(height[left], height[right]) * (right-left));
			if (height[left] > height[right]) {
				-- right;
			} else {
				++ left;
			}
		}
		return area;
    }
}

提交结果如下:

解答成功: 执行耗时:4 ms,击败了67.68% 的Java用户 内存消耗:56.9 MB,击败了23.36% 的Java用户

复杂度分析:

  • 时间复杂度: O(n), 遍历数组
  • 空间复杂度: O(1)