[LeetCode][11]Container With Most Water解析 时间复杂度为O(n) -Java实现
2016-06-12 14:16
573 查看
Q:
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.
A:
这题目还是有点意思的:大概是说在x轴的垂直方向上(即y轴)有一条一条的线,它们以(i,0)开始到(i,ai)结束,挑两个线组成一个最大面积的容器可以装下更多的水。
这里面有一个短板的问题,对于任意两条线ia,ib我们可以得出一个公式S = Math.abs((ia-ib))*Math.min(height[ia],height[ib]).这道题当然我们可以用遍历的方法解决,最简单的遍历时间复杂度应该是O(n^2)很明显这不符合我们的预期。
首先我们要明确一个性质:如果一个容器能有比他更大的容器,突破点一定在高的那个柱子上。
就好像图中的a1区域,要想找到比a1区域更大的区域,肯定最大值在左侧更高的那个柱子上。并且有且只有这一个最大值。
现在我们来严格的证明一下这个性质:
对于1和8来说他们中间相隔的宽度为7,高度8要低一点,假设高为h8,容器面积为s18,那么如果我们不从1找突破点而从8开始的话,如果新的i(1<i<8)的高hi<h8
它的si8 = hi*(8-i)很明显小于s18,翻过来如果hi>h8的话si8 = h8*(8-i)一样的很明显小于s18,所以如果有一个面积大于s18,它的一端一定在1上。
根据上述性质我们终于可以写出来一个时间复杂度为O(n)的程序了
代码如下
这一题关于从左右开弓应该大家都想得到,但是证明可能难了点。
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.
A:
这题目还是有点意思的:大概是说在x轴的垂直方向上(即y轴)有一条一条的线,它们以(i,0)开始到(i,ai)结束,挑两个线组成一个最大面积的容器可以装下更多的水。
这里面有一个短板的问题,对于任意两条线ia,ib我们可以得出一个公式S = Math.abs((ia-ib))*Math.min(height[ia],height[ib]).这道题当然我们可以用遍历的方法解决,最简单的遍历时间复杂度应该是O(n^2)很明显这不符合我们的预期。
首先我们要明确一个性质:如果一个容器能有比他更大的容器,突破点一定在高的那个柱子上。
就好像图中的a1区域,要想找到比a1区域更大的区域,肯定最大值在左侧更高的那个柱子上。并且有且只有这一个最大值。
现在我们来严格的证明一下这个性质:
对于1和8来说他们中间相隔的宽度为7,高度8要低一点,假设高为h8,容器面积为s18,那么如果我们不从1找突破点而从8开始的话,如果新的i(1<i<8)的高hi<h8
它的si8 = hi*(8-i)很明显小于s18,翻过来如果hi>h8的话si8 = h8*(8-i)一样的很明显小于s18,所以如果有一个面积大于s18,它的一端一定在1上。
根据上述性质我们终于可以写出来一个时间复杂度为O(n)的程序了
代码如下
public class ContainerWithMostWater { public static void main(String[] args){ int[] a ={3,1,9,1}; System.out.println(method(a)); } private static int method(int[] a) { // TODO Auto-generated method stub int i = 0; int j = a.length-1; int maxS = 0; int thisS = 0; while(i!=j){ thisS = Math.min(a[i],a[j])*(j-i);//高*宽 maxS = thisS>maxS?thisS:maxS; if(a[i]>a[j]){//突破点在高的柱子上 j--; }else { i++; } } return maxS; } }
这一题关于从左右开弓应该大家都想得到,但是证明可能难了点。
相关文章推荐
- Java创建线程的两个方法
- Android Eclipse安装Ant插件
- java.lang.OutOfMemoryError: PermGen space
- JAVA Calendar详解(转)
- Java WebService 简单实例
- Struts2学习笔记(1)
- POI操作WORD文档,生成的新文档为空白文档 -- 待解决
- Java 集合框架
- spring mvc常用的注解:
- Java 六种异常处理的陋习
- struts2标签详解
- java使用google验证码jar包
- Java编程开发设计模式之--抽象工厂模式(Abstract Factory)
- java 原型模式
- Spring 中的SpEL
- struts2类型转换器日期转换小例详解
- maven工程里面install时jdk报错
- java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: NO)
- java 浮点运算 工具类
- 环形hash算法java实现