leetcode 11. 盛最多水的容器

11. 盛最多水的容器

难度中等

给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0) 。找出其中的两条线,使得它们与 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

示例 3:

输入:height = [4,3,2,1,4]
输出:16

示例 4:

输入:height = [1,2,1]
输出:2

 

提示:

  • n = height.length
  • 2 <= n <= 3 * 104
  • 0 <= height[i] <= 3 * 104

法一:极其朴素的暴力解法(时间超限,中等题目用暴力就是作死)

class Solution {
public:
    int maxArea(vector<int>& height) {
        int n = height.size(), Max = 0;
        for(int i=0; i<n; i++){
            for(int j=1; j<n; j++){
                Max = max(Max, (j-i)*min(height[i], height[j]));
            }
        }
        return Max;
        
    }
};

法二:双指针解法

看了答案我哭了~

思路:

首先,明确一点,结果应该是max{min(height[j], height[i]) * (j-i)}。

现在考虑设置两个指针i和j,分别指向首元素和尾元素。双指针代表的是可以作为容器左边界和右边界的范围。每次都把指向较小元素的那个指针指向下一个元素,就表示这个指针不可能再作为容器的边界了。在遍历过程中就能得到结果。

为啥每次都把指向较小元素的那个指针指向下一个元素呢?

不妨设height[i] 等于 x, height[j] = y, 且x<y. 那么,当前容器容量是min(height[j], height[i]) * (j-i) = x*(j-i);

假设接下来j向左移,height[j-1] = y1. (j-i)一定会变小

1、y1<=y,  min(height[j], height[i]) * (j-i)  = min(x, y1)*(j-i) <=  min(x, y)*(j-i)

2、y1>y, min(height[j], height[i]) * (j-i)  = min(x, y1)*(j-i) = x*(j-i) = min(x,y)*(j-i)

 无论怎么移动右指针,得到的容器容量都小于前容器的容量。

所以,我们应该移动height值较小的那个指针。

class Solution {
public:
    int maxArea(vector<int>& height) {
        int n = height.size(), Max = 0;
        int i = 0, j = n-1;
        while(i < j){
            Max = max(Max, min(height[i], height[j])*(j-i));
            if(height[i] < height[j]) i++;
            else j--;

        }
        return Max;
        
    }
};

法三: 动态规划

 递归法,可以改成法二迭代,这里主要理解思想。

class Solution {
public:
    int getResult(int l, int r, vector<int> &h){
        if(r-l == 1) return min(h[r], h[l]);
        int Max = min(h[r], h[l])*(r-l), subMax = 0;
        if(h[l] < h[r]){
            subMax = getResult(l+1, r, h);
        }
        else
            subMax = getResult(l, r-1, h);
        return max(Max, subMax);
    }
    int maxArea(vector<int>& height) {
        int n = height.size(), Max = 0;
        Max = getResult(0, n-1, height);
        return Max;
    }
};

 

 

 

posted @ 2021-04-21 16:39  深圳地铁Princess  阅读(44)  评论(0编辑  收藏  举报