题目链接
题目描述
给定一个长度为 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 <= 10^5
0 <= height[i] <= 10^4
解题思路
任何容器的面积都是使用较短的线作为长度,线之间的举例作为宽度来计算长方形的面积
暴力法
这是思路最清晰的方法,就是计算所有可能性,然后得到最大面积,但是这种方式的复杂度为O(n^2),在LeetCode上面直接超时了
暴力法代码
class Solution {
public int maxArea(int[] height) {
int ans = 0;
int area = 0;
for (int i = 0; i < height.length; i++) {
for (int j = i; j < height.length; j++) {
area = Math.min(height[i], height[j]) * (j - i);
ans = Math.max(area, ans);
}
}
return ans;
}
}
双指针法
设left = 0
, right = height.length - 1
,那么初始时宽度是最大的,下一步就是考虑移动左右窗口
- 因为不管是
left++
还是right--
,都会使得窗口宽度–,那么就选择移动后的容器的高度尽量大,所以我 - 所以我们选择指针所指的高较小的那个指针来进行移动,这样我们就保留了容器较高的那条边,以获得有更高的边的机会
AC代码
class Solution {
public int maxArea(int[] height) {
int ans = 0;
int area = 0;
int left = 0;
int right = height.length - 1;
while (left < right) {
area = Math.min(height[left], height[right]) * (right - left);
ans = Math.max(ans, area);
if (height[left] < height[right]) {
left++;
} else {
right--;
}
}
return ans;
}
}