[LeetCode] Container with most water

来源:互联网 发布:uncomtrade数据库 编辑:程序博客网 时间:2024/06/05 01:58

这几天刷leetcode,才做了几道题,就被打击的自信全无。各种拼写错误,各种边界值问题,被折磨的死去活来。。。分享一道简单的,我会写的,提升下士气。。。

题目:在xy坐标平面上,有一串点(1,a1),(2,a2),(3,a3),…(n,an). 任意两点与x轴的连线再加上x轴,都可以构成一个三条边的桶形。求最大的桶能装多少水。。。

第一眼看到题目的思路是,f(i,j)=(ij)min(a[i],a[j]),求max(f(i,j))
按照公式,两个循环搞定。无空间复杂度,时间复杂度O(n2)。

但是,这解法也太简单粗暴了。如果只是为了能跑起来,这样还行得通,但性能上实在是有点惨。
脑海中想象一下图形,可以发现,对于固定的a[i],利用数轴的特性,
如果a[j]<a[j+1]

简单优化一下,代码如下

public class Solution {    public int maxArea(int[] height) {        int max = 0;        int length = height.length;        for(int i=0; i< length; i++){            for(int j=i+1; j<length; j++){                int b = height[j];                //如果下一个数值比本次的更大,就没必要计算max,直接跳过。                if(j+1<length){                    if(height[j+1] >= b){                        continue;                    }                }                int a = height[i];                max = Math.max(max,(j-i)*Math.min(a,b));            }        }        return max;    }}

假设,数值是随机的,后一个数字比前一个数字大的概率是50%。
性能的话,明显多加了o(n2)次的判断,减少了差不多一半的sum的计算。但是,提升不明显啊。

仔细分析一下程序的执行过程,对于任何一个i,循环j要执行length-i次。即使,明明已经知道了某个a[j]<a[j+1]

总结一下思路,
如果a[jt]<a[j]
如果a[i+t]<a[i]
在坐标轴上,可以想象为,从两端开始算起,有且只有找到能有效提高height的数值时,才可能大于之前的盛水量。
那么,把两个公式结合起来用一下
如下:

public class Solution {    public int maxArea(int[] height) {        int max = 0;        int length = height.length;        int h;        for(int i=0,j =length-1; i<j;){          h = Math.min(height[i], height[j]);          max = Math.max(max, (j-i)*h);          //直到找到比当前高度更高的i和j,才进行一次计算          while(h >= height[i] && i<j){              i++;          }          while(h >= height[j] && i<j){              j--;          }        }        return max;    }

时间复杂度降低到O(n)了。这里的h起到了之前的maxj的标记值的作用。

0 0
原创粉丝点击