博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
LeetCode (11): Container With Most Water
阅读量:6541 次
发布时间:2019-06-24

本文共 2715 字,大约阅读时间需要 9 分钟。

https://leetcode.com/problems/regular-expression-matching/

【描述】

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.

【中文描述】

给一个int数组,a1,a2,a3,....an,n个数。然后假设有一个坐标系,x轴就是i,y轴的长度就是给的各个数字ai。 假想有n条竖线,每条线的下端就是点(i, 0),上端是(i, ai)。现在假想往这些线组成了N多个容器。往这些线中间倒水,要求找出其中两条线,使得在这两条线内倒水时,可以装的水最多。

————————————————————————————————————————————————————————————

【初始思路】

这道题确实很有意思,简单思考一下就知道,两条线间能盛水的最高高度取决于这两条线里哪根短。短的高度 * 两条线间距,就是所盛水的体积。

那么,怎么找这两条线呢?最简单的办法永远是brutal解法,i.j两套循环,记录中间出现的最大体积,循环结束后返回即可。时间复杂度是O(N2),leetCode肯定不会接受吧。

那还能怎么找,这就是这个题好玩的地方了!

 

【另辟蹊径】

假设给的数组就只有2个数字,那么很显然,最大的线就是这两条线。如果是3个数字呢,你会怎么做?我们还是可以从两边先算一个盛水量出来,然后分别算两条边和中间这条线之间的盛水量,最后3个量做个比较,给出最大值。推到N个数字呢?其实就是2个数字到3个数字的思维过程。

我们每次都从两边开始,先算一个盛水量,然后慢慢把两边往里面收,过程中记录最大的体积。等两边不断向中间靠近的时候,最终会遇到一起。那这N个数字就遍历完了,最大盛水量不就出来了么?

可是有左右两个边,怎么收是个问题。这两条边肯定一个高,一个低,按照直觉,你会舍弃哪个?保留哪个?当然,低的舍弃掉,往里看看还有没有更高的!

理性的分析呢?

我们假设每次舍弃高的一边height2(低的一边为height1),高的一边往里推移一位,得到新的newHeight2,同时假设newHeight2 > height1。由于往里推移了一位,width1变为width2,显然width2<width1。那么重新计算的area1 = height1 * width2 < height * width1.  这样求出的area,还有什么必要去和之前的area比大小么?肯定比之前的小!

如果假设newHeight2 < height1, 那么area1肯定更小了。这样岂不是越比越小?那么等到两边不断缩进到里面的时候,体积只会越比越小,最大体积相当于就是最开始两边决定的体积。这肯定不合理(虽然在个别情况下,这是有可能的,但是绝大多数情况下,这不可能!)。如果绝大多数情况下不可能,这个方法肯定不对啊!

分析结束!

 

【Show me the Code!!!】

1  /** 2      * 这个思路简直碉堡了! 3      * @param height 4      * @return 5      */ 6     public static int maxAreaLinear(int[] height) { 7         if(height.length==0 || height ==null) return 0; 8         int maxArea = 0; 9         int left = 0;10         int right = height.length - 1;11 12         while (left < right) {13             int minHeight = Math.min(height[left], height[right]);14             maxArea = Math.max(maxArea, minHeight * (right - left));15             if(height[left] <= height[right]) left++;16             else right--;17         }18         return maxArea;19     }
maxAreaLinear

 

【follow-up】

如果两条线组成的桶可以倾斜呢?又如何找?

由于倾斜后成了一个梯形,首先温习梯形面积公式:(上底+下底)* 高/2。  那么当两条线(an, am)组成了梯形后,它的面积其实就是(am+an)*(m-n) / 2

(1)思路可以延续上面题目,还是假设初始用最左右两边围成一个梯形,然后算面积,易求area1;

(2)接下来和上面就有点区别了,因为可以倾斜,所以我们直接找i, j 之间最高的线, ak。显然,现在被分成了2个梯形,分别算出其面积,和之前的做比较。如果area1最大,那最大面积就是area1,如果后面得到的两个梯形其中一个更大。更新最大area。

(3)由于存在ak,把0->n分成了2份。 1->k-1, k+1->n-1。由于在(2)里,两个梯形一个大,一个小。我们假设右边的小,左边的大。那么右边的点k+1->n-1可以全部被舍弃掉了。因为他们高度没有ak高,他们无论怎么围,面积都不可能超过目前最大面积。

(4)再看看左边,在1->k-1中间继续找最大值,把左边梯形分成了更小的两个,再分别算面积,看哪个最大。如果原来左边的大,那么最大面积就是左边这个梯形。如果两个子梯形里有一个更大,那么重复(2)(3)(4)步骤。直到最后没有再分的余地。

 

 

 

转载于:https://www.cnblogs.com/lupx/p/leetcode-11.html

你可能感兴趣的文章
JQUERY 对 表格中的数据重排序
查看>>
程序员常用借口指南
查看>>
关于PXE网络安装linux系统中碰到的个别问题
查看>>
awk 常用方法
查看>>
Android网络框架实现之【Retrofit+RxJava】
查看>>
Android文件的加密与解密
查看>>
SOAP webserivce 和 RESTful webservice 对比及区别
查看>>
【原】记录一句话
查看>>
Android标题栏,状态栏
查看>>
Windows下安装Memcached for PHP
查看>>
hdu 1040 As Easy As A+B
查看>>
java笔记:SpringSecurity应用(二)
查看>>
php记录代码执行时间
查看>>
【C】strcpy()需谨慎使用;
查看>>
用Adobe Flash Professional CS6创建一个iOS应用程序
查看>>
简简单单几段代码让自己变成最合格的网站管理员
查看>>
Slim Text 0.0.9 发布, 代码开源!
查看>>
[置顶] 遵循Java EE标准体系的开源GIS服务平台之二:平台部署
查看>>
Session深度探索
查看>>
shell语法简单介绍
查看>>