例题:
给你 n 个非负整数 a1,a2,…,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

说明:你不能倾斜容器,且 n 的值至少为 2。

判断两个容器是否通信 如果两个不同容器_两个指针

示例:

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

输出:49

这道题目简单来说就是x轴乘y轴能够得到的最大面积(y轴取较小的那一个)

这道题目采取双指针法解题(后面我们再讲解双指针法的正确性)
示例:[1,8,6,2,5,4,8,3,7]
分析:
首先,将左右指针分别放在数组左右两端。
面积公式就是:两个指针指向的数字中较小值∗指针之间的距离

此时有 最大容量: min (1,7) * 8 = 8 ⇒ min(nums[0],nums[8]) * (8-0)

此时我们要开是移动指针,我们可以分析得到我们应该移动较小的那个指针也就是左指针,如果我们移动较大的那个指针,因为前面较小的值没有变化,并且间隔减小,这个乘机就减小了。所以我们移动数字较小的那个指针。

所以,我们将左指针向右移动:[x,8,6,2,5,4,8,3,7]
容纳的水量为 min⁡(8,7)∗7=49。

由于右指针对应的数字较小,我们移动右指针:[x,8,6,2,5,4,8,3,x]
容纳的水量为 min⁡(8,3)∗6=18。

由于右指针对应的数字较小,我们移动右指针:[x,8,6,2,5,4,8,x,x]
此时可以容纳的水量为 min⁡(8,8)∗5=40。

两指针对应的数字相同,我们可以任意移动一个,例如左指针:[x,x,6,2,5,4,8,x,x]
容纳的水量为 min⁡(6,8)∗4=24。

由于左指针对应的数字较小,我们移动左指针,并且可以发现,在这之后左指针对应的数字总是较小,因此我们会一直移动左指针,直到两个指针重合。在这期间,对应的可以容纳的水量为:min⁡(2,8)∗3=6,min⁡(5,8)∗2=10,min⁡(4,8)∗1=4

所以从我们记录的值可以得出最大融水量为49

为什么我们双指针法是正确的(移动哪一个指针)
在我们选择移动指针的时候,我们无非就是两个选择:左指针和右指针。当我们移动较大的那个指针时,我们的值只会比原来的值小(两个指针指向的数字中较小值∗指针之间的距离),那么我们移动这个指针得到的值没有任何意义(要求最大值)。因为对于较小的这个指针我们已经获取到了它的最大值,我们可以舍弃掉这个左边界(这就是为什么要把左右指针放在左右两边)

所以我们应该移动指针较小的这个指针,这样相当于每次我们都排除掉一个边界,将问题的规模减小了1。被丢弃的那个位置相当于消失了。时的左右指针,就指向了一个新的、规模减少了的问题的数组的左右边界

代码

class Solution {
    public int maxArea(int[] height) {
        int left = 0,right = height.length-1;
        int ans = 0;
        while(left < right){
            int hei = Math.min(height[left],height[right]);
            ans = Math.max(ans, hei*(right-left));
            if(height[left] <= height[right]){
                left++;
            }else{
                right--;
            }
        }
        return ans;
    }
}