Container With Most Water

题目链接

Given n non-negative integers a1, a2, ..., an, where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at (i, ai) 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.


算法1:枚举容器的两个边界,时间复杂度O(n^2)。大数据超时

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

 

对上面的稍加改进,根据当前的已经计算出来的结果以及左边界的值,可以算出容器右边界的下界。不过还是超时

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

 

算法2:时间复杂度O(nlogn)。

构建结构体包含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;
}
};

 

 

算法3:时间复杂度O(n),两个指针i, j分别从前后向中间移动,两个指针分别表示容器的左右边界。每次迭代用当前的容量更新最大容量,然后把高度小的边界对应的指针往中间移动一位。                                         本文地址

正确性证明:由于水的容量是有较小的那个边界决定的,因此某次迭代中,假设height[i] < height[j],那么j 减小肯定不会使水的容量增大,只有i 增加才有可能使水的容量增大。但是会不会有这种可能:当前的i 和 某个k (k > j)是最大容量, 这也是不可能的,因为按照我们的移动规则,既然右指针从k 移动到了j,说明i 的左边一定存在一个边界 m,使m > k,那么[m, k]的容量肯定大于[i, k],所以[i,k]不可能是最大容量。可以参考here

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

Trapping Rain Water

Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining.

For example,

Given [0,1,0,2,1,0,1,3,2,1,2,1], return 6.

The above elevation map is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped.

注意和上一题的区别,上一题相当于在每个位置放一个挡板,挡板之间可以蓄水;这一题是放置宽度为1的柱子,柱子上面可以蓄水。

 

算法4:分析某个柱子,发现该柱子上水的高度和其左右两边的最高柱子有关,设该柱子左边所有柱子中最高的为leftmax,右边所有柱子中最高的为rightmax,如果min(leftmax, rightmax) 大于该柱子的高度,那么该柱子上可以蓄水为min(leftmax, rightmax) - 该柱子高度,如果min(leftmax, rightmax) <= 该柱子高度,则该柱子上没有蓄水。

可以从后往前扫描一遍数组求得某个柱子右边的最高柱子,从前往后扫描一遍数组求得某个柱子左边的最高柱子, 然后按照上面的分析可以求得所有的蓄水量。

class Solution {
public:
int trap(int A[], int n) {
int res = 0;
vector<int>rightMax(n);//柱子右边最大的柱子高度
int maxv = 0;
for(int i = n-1; i >= 0; i--)
{
rightMax[i] = maxv;
maxv < A[i] ? maxv = A[i] : maxv;
}
maxv = 0;
int conHeight;
for(int i = 0; i < n; i++)
{//此时maxv为柱子i左边最大的柱子高度
conHeight = min(maxv, rightMax[i]);
if(conHeight > A[i])
res += conHeight - A[i];
maxv < A[i] ? maxv = A[i] : maxv;
}
return res;
}
};

上面的代码时间空间复杂度都是O(n),扫描了两次数组

 

算法5:可以换一种思路,如下图,如果我们求出了两个红色框的面积,然后再减去框内黑色柱子的面积,就是水的面积了,时间复杂度O(N),空间O(1), 数组扫描2次

如何求红色框内的面积呢,我们先求出最大的柱子高度,然后左右分开求。求面积是是一层一层的累加

class Solution {
public:
int trap(int A[], int n) {
int maxHeight = 0, maxIdx = 0;
for(int i = 0; i < n; i++)//求最大高度
if(A[i] > maxHeight)
{
maxHeight = A[i];
maxIdx = i;
}
int height = 0;
int pillarArea = 0;//柱子面积
int totalArea = 0;//总面积
for(int i = 0; i < maxIdx; i++)
{
if(A[i] > height)
{
totalArea += (A[i] - height)*(maxIdx - i);
height = A[i];
}
pillarArea += A[i];
}
height = 0;
for(int i = n-1; i > maxIdx; i--)
{
if(A[i] > height)
{
totalArea += (A[i] - height)*(i - maxIdx);
height = A[i];
}
pillarArea += A[i];
}
return totalArea - pillarArea;
}
};

 

算法6:参考here,也是和算法5一样求面积,但是这里利用上一题的左右指针思想,只需要扫描一遍数组

class Solution {
public:
int trap(int A[], int n) {
int left = 0, right = n-1;
int totalArea = 0, pillarArea = 0, height = 0;
while(left <= right)
{
if(A[left] < A[right])
{
if(A[left] > height)
{
totalArea += (A[left]-height)*(right - left + 1);
height = A[left];
}
pillarArea += A[left];
left++;
}
else
{
if(A[right] > height)
{
totalArea += (A[right]-height)*(right - left + 1);
height = A[right];
}
pillarArea += A[right];
right--;
}
}
return totalArea - pillarArea;
}
};

 

 

【版权声明】转载请注明出处http://www.cnblogs.com/TenosDoIt/p/3812880.html

LeetCode:Container With Most Water,Trapping Rain Water的更多相关文章

  1. [LeetCode] 接雨水,题 Trapping Rain Water

    这题放上来是因为自己第一回见到这种题,觉得它好玩儿 =) Trapping Rain Water Given n non-negative integers representing an eleva ...

  2. 【LeetCode每天一题】Trapping Rain Water(获得雨水的容量)

    Given n non-negative integers representing an elevation map where the width of each bar is 1, comput ...

  3. LeetCode 42. 接雨水(Trapping Rain Water)

    题目描述 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水. 上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况 ...

  4. leetcode 11. Container With Most Water 、42. Trapping Rain Water 、238. Product of Array Except Self 、407. Trapping Rain Water II

    11. Container With Most Water https://www.cnblogs.com/grandyang/p/4455109.html 用双指针向中间滑动,较小的高度就作为当前情 ...

  5. [LeetCode] Trapping Rain Water 收集雨水

    Given n non-negative integers representing an elevation map where the width of each bar is 1, comput ...

  6. [LeetCode] 42. Trapping Rain Water 收集雨水

    Given n non-negative integers representing an elevation map where the width of each bar is 1, comput ...

  7. [LeetCode] Trapping Rain Water II 收集雨水之二

    Given an m x n matrix of positive integers representing the height of each unit cell in a 2D elevati ...

  8. [Leetcode][Python]42: Trapping Rain Water

    # -*- coding: utf8 -*-'''__author__ = 'dabay.wang@gmail.com' 42: Trapping Rain Waterhttps://oj.leetc ...

  9. leetcode#42 Trapping rain water的五种解法详解

    leetcode#42 Trapping rain water 这道题十分有意思,可以用很多方法做出来,每种方法的思想都值得让人细细体会. 42. Trapping Rain WaterGiven n ...

随机推荐

  1. Java 基本数据类型长度

    System.out.println(Integer.MAX_VALUE-(-Integer.MAX_VALUE)); //内存溢出System.out.println(Integer.MAX_VAL ...

  2. 1029. Median (25)

    分析: 考察归并排序,用简单的快排会超时. #include <iostream> #include <stdio.h> #include <algorithm> ...

  3. Git平台使用时的配置分析

    Git仓库的配制文件分为三个部分: 1. .git/config:指定仓库配置(特定于某个仓库),获取或设置时使用--file参数(或者省去). 2. ~/.gitconfig:用户级别仓库配置(适用 ...

  4. 隐马尔科夫模型HMM学习最佳范例

    谷歌路过这个专门介绍HMM及其相关算法的主页:http://rrurl.cn/vAgKhh 里面图文并茂动感十足,写得通俗易懂,可以说是介绍HMM很好的范例了.一个名为52nlp的博主(google ...

  5. kettle etl

    使用注意点 1 如果服务器资源有限的话,尽量少开任务窗口,但是要有容错机制,可以分为按天按分钟 2 如果不想写较长的sql可以用detail来启动 3 在设置每天提交的条数时,如果数据很少,而设置值很 ...

  6. Wordnet的一些简单使用

    转载请说明出处:http://www.cnblogs.com/KingKou/p/4121373.html 1.简介 Wordnet是一个由普林斯顿大学认识科学实验室在心理学教授乔治·A·米勒的指导下 ...

  7. log_reuse_wait_desc为REPLICATION,日志暴大,无法收缩

    早上检查数据发现,有一台数据的硬盘空间只剩下几MB.习惯性检查日志文件,发现日志文件居然暴增到了350多GB 首先备份日志,再收缩-------无变化.(实际上日志备份每1小时1挡,正常在跑.) -- ...

  8. Gedit中文乱码

    缺省配置下,用 Ubuntu 的文本编辑器(Gedit)打开GB18030(繁体中文用户请将这里的出现的GB18030替换成BIG5或BIG5-HKSCS)类型的中文编码文本文件时,将会出现乱码. 出 ...

  9. Dynamic CRM 2013学习笔记(二十一)自定义审批流2 - 配置按钮

    上次介绍了 Dynamic CRM 2013学习笔记(十九)自定义审批流1 - 效果演示 现在开始介绍如何配置审批流,首先在form上添加三个按钮,Submit, Agree, Reject: 1. ...

  10. WinServer2008 R2搭建TFS2013小结(无法连接Internet手动安装)

    不定时更新参考文档: TFS安装与管理 为本地管理配置本机模式报表服务器 (SSRS) 手里有文档还是掉进各种坑,这里把坑总结一下,方面以后填坑. 安装指导文档中搭建TFS2013用了两台服务器,把S ...