[11]盛最多水的容器
1、题目
给定一个长度为 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
2 <= n <= 105
0 <= height[i] <= 104
Related Topics
- 贪心
- 数组
- 双指针
2、题目分析
本题是求任意两线间的面积,面积 = 长 * 宽,故两线间的面积 = 两线间的下标距离 * 两线较小高。
其中有2个变量:
两线间的下标距离;
两线较小高;
在有 2 个变量同时影响结果时,初步就是 n*n 的复杂度。
此时可以考虑以下优化:
判断某个变量是否能直接拉到最满足结果的极值,然后该变量依次减弱时只需考虑对另外一个变量的处理方案,这样就把n*n的复杂度优化成n
3、解题步骤
- 初始化两个指针 left 和 right,分别指向数组的第一个元素和最后一个元素。
- 初始化 max_area 为 0,用于存储最大水量。
- 当 left < right 时,执行以下操作:
3.1 计算当前两个指针所指向的线段的最小高度:h = min(height[left], height[right])。
3.2 根据最小高度更新 max_area:max_area = max(max_area, h * (right - left))。
3.3 如果 height[left] < height[right],则将 left 向右移动一位;否则,将 right 向左移动一位。 - 返回 max_area。
4、复杂度最优解代码示例
public int maxArea(int[] height) {
// 1. 初始化两个指针 left 和 right,分别指向数组的第一个元素和最后一个元素。
int left = 0;
int right = height.length - 1;
// 2. 初始化 max_area 为 0,用于存储最大水量。
int maxArea = 0;
while (left < right) {
// 3. 当 left < right 时,执行以下操作:
// 3.1 计算当前两个指针所指向的线段的最小高度:h = min(height[left], height[right])。
int minHeight = Math.min(height[left], height[right]);
// 3.2 根据最小高度更新 max_area:max_area = max(max_area, h * (right - left))。
maxArea = Math.max(maxArea, minHeight * (right - left));
// 3.3 如果 height[left] < height[right],则将 left 向右移动一位;否则,将 right 向左移动一位。
// △踩坑,不能直接写 left++、right--;而应该是高的线条不移动,因为压缩距离后,可能因为旧线条足够高,和新的线条勾勒出更大的面积
if (height[left] > height[right]) {
right--;
} else {
left++;
}
}
// 4. 返回 max_area。
return maxArea;
}
5、抽象与扩展
在有 2 个变量同时影响结果时,初步就是 n*n 的复杂度。
此时可以考虑以下优化:
假设将某个变量直接拉到最满足结果的极值,然后该变量依次减弱时只需考虑对另外一个变量的处理方案,这样就把n*n的复杂度优化成n