题目

给你 n 个非负整数 11. 盛最多水的容器 - 图1,每个数代表坐标中的一个点 11. 盛最多水的容器 - 图2 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 11. 盛最多水的容器 - 图311. 盛最多水的容器 - 图4。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
说明: 你不能倾斜容器

示例1
image.png

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

实现

思路1 暴力解法

利用两重循环枚举所有可能的左右边情况,计算所有面积后取最大值。

时间复杂度11. 盛最多水的容器 - 图6
空间复杂度11. 盛最多水的容器 - 图7

思路2 双指针法

需要移动左右两头的问题可以考虑双指针。这样难点就在于如何移动双指针。
首先我们根据面积计算方式知道

  • 两边距离要尽量远
  • 面积受限于较短边

根据第一点我们可以让右指针从最右边往左移动,这样如果移动后的边比移动前的边短或者一样长,就可以跳过面积计算。因此移动后宽变小了,如果高也变小,那面积肯定比移动前更小。
根据第二点我们可以决定左右两个指针何时移动,即当右边比左边长时,固定右指针,移动左指针;当左边比右边长时则移动右指针。

class Solution {
public:
    int maxArea(vector<int>& height) {
        int max_area = 0, left = 0, right = height.size()-1;
        while(left < right){
            // 计算当前最大盛水面积
            max_area = max((right-left) * min(height[left],height[right]), max_area);

            // 移动指针
            if(height[left]<height[right])
                left++;
            else
                right--;
        }
        return max_area;

    }
};

运行结果
image.png
时间复杂度11. 盛最多水的容器 - 图9
空间复杂度11. 盛最多水的容器 - 图10