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

题解: 先来了一发n^2的暴力,。。竟然能过

class Solution {
public:
    int maxArea(vector<int>& height) {
        int n = (int)height.size();
        int ans = 0;
        for (int i = 0; i < n; ++i){
            for (int j = i + 1; j < n; ++j){
                int top = height[j] > height[i] ? height[i] : height[j];
                int water = top * (j - i);
                if (water > ans) ans = water;
            }
        }
        return ans;
    }
};

然后思考了一下在left = 0和right = n-1的位置放一个指针,两边位置小的指针向中间移动,一直到left = right,记录移动过程中的最大值就是答案。

Q:为什么这样就不会错过最大值的区间?

A:策略其实就是贪心的策略,移动高的一侧对结果不可能会有帮助,只有移动低的一侧才有可能使结果变大,最大值区间会在移动过程中遇到。有点说不明白,可以去看官方题解,里面有清楚的证明过程:https://leetcode-cn.com/problems/container-with-most-water/solution/container-with-most-water-shuang-zhi-zhen-fa-yi-do/

class Solution {
public:
    #define Min(a,b) (a > b ? b : a)
    #define Max(a,b) (a > b ? a : b)
    int maxArea(vector<int>& height) {
        int n = (int)height.size();
        int ans = Min(height[0], height[n - 1]) * (n - 1);
        int left = 0, right = n - 1;
        while(left < right) {
            if (height[left] < height[right]) left ++;
            else right --;
            ans = Max(ans, (Min(height[left], height[right])) * (right - left));
        }
        return ans;
    }
};
02-10 21:41