[LeetCode]11.Container With Most Water

简介:

【题目】

Given n non-negative integers a1a2, ..., an, where each represents a point at coordinate (iai). n vertical lines are drawn such that the two endpoints of line i is at (iai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water.

Note: You may not slant the container.

【分析一】

最直接的思路是暴力枚举法,枚举容器的两个边。O(n^2)。超时。

【代码一】

/*********************************
*   日期:2015-01-21
*   作者:SJF0115
*   题目: 11.Container With Most Water
*   网址:https://oj.leetcode.com/problems/container-with-most-water/
*   结果:Time Limit Exceeded
*   来源:LeetCode
*   博客:
**********************************/
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

class Solution {
public:
    int maxArea(vector<int> &height) {
        int count = height.size();
        if(count <= 1){
            return 0;
        }//if
        int maxArea = 0;
        // 左边界
        for(int i = 0;i < count-1;++i){
            // 右边界
            for(int j = i+1;j < count;++j){
                int area = (j - i) * min(height[i],height[j]);
                maxArea = max(area,maxArea);
            }//for
        }//for
        return maxArea;
    }
};

int main(){
    Solution solution;
    vector<int> vec;
    vec.push_back(2);
    vec.push_back(3);
    vec.push_back(1);
    vec.push_back(4);
    vec.push_back(2);
    int result = solution.maxArea(vec);
    // 输出
    cout<<result<<endl;
    return 0;
}


【分析二】

当从两边向中间考虑时,面积 =  两端较小的高度×两边之间的宽度。
假定初始的盛水面积为area=0,如果左边的高度小于右边的高度,容器左边向右运动一位。同理,如果右边的高度小于左边的高度,则向左运动一位。

【代码二】

/*********************************
*   日期:2015-01-21
*   作者:SJF0115
*   题目: 11.Container With Most Water
*   网址:https://oj.leetcode.com/problems/container-with-most-water/
*   结果:AC
*   来源:LeetCode
*   博客:
**********************************/
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

class Solution {
public:
    int maxArea(vector<int> &height) {
        int count = height.size();
        if(count <= 1){
            return 0;
        }//if
        int maxArea = 0,area = 0;
        // 二分查找变形
        for(int i = 0,j = count-1;i < j;){
            // 去掉低的一边
            if(height[i] > height[j]){
                area = (j - i) * height[j];
                --j;
            }//if
            else{
                area = (j - i) * height[i];
                ++i;
            }//else
            // 更新最大面积
            if(area > maxArea){
                maxArea = area;
            }//if
        }//for
        return maxArea;
    }
};

int main(){
    Solution solution;
    vector<int> vec;
    vec.push_back(2);
    vec.push_back(3);
    vec.push_back(1);
    vec.push_back(4);
    vec.push_back(2);
    int result = solution.maxArea(vec);
    // 输出
    cout<<result<<endl;
    return 0;
}


【分析三】

当从两边向中间考虑时,面积 =  两端较小的高度×两边之间的宽度。
假定初始的盛水面积为area=0,如果左边的高度小于右边的高度,容器左边向右运动,直到找到一个比原先左边高度高的。
同理,如果右边的高度小于左边的高度,则向左运动,直到找到一个比原先右边高度高的。

【代码三】

class Solution {
public:
    int maxArea(vector<int> &height) {
        int count = height.size();
        if(count <= 1){
            return 0;
        }//if
        int index,maxArea = 0,area = 0;
        // 二分查找变形
        for(int i = 0,j = count-1;i < j;){
            // 去掉低的一边
            if(height[i] > height[j]){
                area = (j - i) * height[j];
                index = j;
                // 向左移动,直到找到一个比height[index]高的
                while(height[j] <= height[index]){
                    --j;
                }//while
            }//if
            else{
                area = (j - i) * height[i];
                index = i;
                // 向右移动,直到找到一个比height[index]高的
                while(height[i] <= height[index]){
                    ++i;
                }//while
            }//else
            // 更新最大面积
            if(area > maxArea){
                maxArea = area;
            }//if
        }//for
        return maxArea;
    }
};


【分析四】

构建结构体包含height和height在原数组中的位置

struct Node 
    { 
        int height; 
        int index;

};

对该结构体数组按照height的值递增排序,假设排序后的数组为vec.

 

假设f[i] 表示数组vec[i,i+1,…]内所有height按照原来的位置顺序排列好以后的最大水量

那么f[i-1]可以在O(1)时间内计算出来:因为vec[i-1].height 小于vec[i,i+1,…]内的所有height,所以以vec[i-1].index为边界的容器高度为vec[i-1].height,最大水量只需要分别计算vec[i,i+1,…]内按原始位置排列最前面和最后面的height,取两者的较大值。即下图中,黑色是最低的,要计算以黑色为边界的容器的最大水量,只需要分别和第一个和最后一个计算,去两者较大值


【代码四】

class Solution {
    struct Node
    {
        int height;
        int index;
        Node(int h, int i):height(h),index(i){}
        Node(){}
        bool operator < (const Node &a)const
        {
            return height < a.height;
        }
    };
public:
    int maxArea(vector<int> &height) {
        int res = 0, n = height.size();
        if(n <= 1)return 0;
        vector<Node>vec(n);
        for(int i = 0; i < n; i++)
        {
            vec[i].index = i;
            vec[i].height = height[i];
        }
        sort(vec.begin(), vec.end());
         
        int start = vec[n-1].index, end = start;//记录已经处理完的height的原始位置的左右端点
        for(int i = n-2; i >= 0 ; i--)
        {
            start = min(start, vec[i].index);
            end = max(end, vec[i].index);
            res = max(res, max(vec[i].height*(vec[i].index - start), vec[i].height*(end - vec[i].index)));
        }
        return res;
    }
};



类似题目:

庞果网之寻找直方图中面积最大的矩形

LeetCode之Trapping Rain Water



目录
相关文章
|
人工智能 容器
Leetcode 11. Container With Most Water
题目可以这么理解,在i位置有条高为ai的竖线,让你选出两台竖线构成一个容器,使得该容器装的水最多,注意容器不能倾斜。
126 3
Leetcode 365. Water and Jug Problem
一句话理解题意:有容积为x和y升的俩水壶,能不能量出z升的水。 我刚开始看到这题,立马就想了下暴力搜索的可能性,但考虑了下数据大小,立马放弃这个暴力的想法,于是意识到肯定有比较简单的数学方法,其实我自己没想到,后来看还是看了别人的代码,很多博客都直接给出了解法, 但没介绍为什么能这么解。所以我决定解释下我自己的思路。
158 0
LeetCode 417. Pacific Atlantic Water Flow
给定一个 m x n 的非负整数矩阵来表示一片大陆上各个单元格的高度。“太平洋”处于大陆的左边界和上边界,而“大西洋”处于大陆的右边界和下边界。 规定水流只能按照上、下、左、右四个方向流动,且只能从高到低或者在同等高度上流动。 请找出那些水流既可以流动到“太平洋”,又能流动到“大西洋”的陆地单元的坐标。
212 0
LeetCode 417. Pacific Atlantic Water Flow
LeetCode 407. Trapping Rain Water II
我们把最外面的四边当成四面墙,想象海水面不断的升高,首先会浸过墙面最低的格子,如果墙面最低格子的四周(出了在墙面的格子)有比它矮的格子,那么这就可以形成一个蓄水池,蓄水池的最高高度就是墙面最低的格子,于是我们计算这个蓄水池可以获得的蓄水量;然后这个蓄水池被添加到墙面中;继续在墙面中找最低的格子;
277 0
LeetCode 407. Trapping Rain Water II
|
索引
LeetCode 42 Trapping Rain Water
给定n个非负整数,每个非负整数表示一个宽度为1的柱子,计算下雨后能够捕获多少水.
152 0
LeetCode 42 Trapping Rain Water
|
机器学习/深度学习 PHP 索引
[Leetcode 之 PHP 解析 (42. Trapping Rain Water)
[Leetcode 之 PHP 解析 (42. Trapping Rain Water)
229 0
[Leetcode 之 PHP 解析 (42. Trapping Rain Water)
|
容器
Leetcode-Medium 11. Container With Most Water
Leetcode-Medium 11. Container With Most Water
167 0
Leetcode-Medium 11. Container With Most Water
|
数据库
LeetCode(数据库)- The Airport With the Most Traffic
LeetCode(数据库)- The Airport With the Most Traffic
218 0
LeetCode - 42. Trapping Rain Water
42. Trapping Rain Water  Problem's Link  ---------------------------------------------------------------------------- Mean:  在坐标上给你一些竖直放置的条形积木,问你这个积木能够容纳多少液体.
991 0