题目描述:
给你 n n n 个非负整数 a 1 a_1 a1, a 2 a_2 a2,…, a n a_n an,每个数代表坐标中的一个点 ( i i i, a i a_i ai) 。在坐标内画 n n n条垂直线,垂直线 i i i的两个端点分别为 ( i i i, a i a_i ai) 和 ( i i i, 0) 。找出其中的两条线,使得它们与 x x x轴共同构成的容器可以容纳最多的水。
说明:你不能倾斜容器。
示例1:
解题思路:
1、双指针:
这道题主要使用左右指针 l e f t left left和 r i g h t right right,分别初始化为 0 0 0和 l e n − 1 len - 1 len−1,计算出两个点( l e f t left left, a l e f t a_{left} aleft)和( r i g h t right right, a r i g h t a_{right} aright)之间所能组成的最大容器面积,根据题意,面积 a r e a = M a t h . m i n ( a l e f t , a r i g h t ) ∗ ( r i g h t − l e f t ) area = Math.min(a_{left},a_{right}) *(right - left) area=Math.min(aleft,aright)∗(right−left),然后更新最大面积。
更新 l e f t 、 r i g h t left、right left、right指针的过程:
假设 a l e f t < a r i g h t a_{left} < a_{right} aleft<aright,即 a l e f t a_{left} aleft为较小的高度,这时更新 l e f t left left: l e f t left left减一,否则更新 r i g h t right right: r i g h t right right加一,这样不断重复上述过程,直至 l e f t = = r i g h t left == right left==right。
以上的过程的正确性证明:
当固定较低的柱子 a l o w a_{low} alow,移动较高一边的柱子 a h i g h a_{high} ahigh,那么有两种情况:(1)遇到不比 a h i g h a_{high} ahigh低的柱子;(2)遇到比 a h i g h a_{high} ahigh低的柱子。这两种情况下容器的高度分别保持不变和变低,都一定不会变高(这是因为容器的高度取最低的那根柱子),而宽度一定减少,所以水的面积一定减少。因此只有移动较低的柱子才有可能出现较大的面积。
时间复杂度和空间复杂度: 时间复杂度为 O ( N ) O(N) O(N) ,空间复杂度为 O ( 1 ) O(1) O(1)
实现代码:
public int maxArea(int[] height) {
if(height == null)
return 0;
int res = 0, len = height.length;
int left = 0, right = len - 1;
while(left < right){
int area = (right - left) * Math.min(height[left], height[right]);//计算面积
res = Math.max(res, area);//更新最大面积
if(height[left] < height[right])//移动较低的柱子
left++;
else
right--;
}
return res;
}