11.Container With Most Water

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.

在平面直角坐标系中,vector 中的下标构成了x轴上的点,下标对应的数字构成了y轴上的点,从(x,0)到(x, y)练成一条线,于是整个vector中的数据构成了一条条的数值线段。我们从这些线段中挑出两条线段,以两条线段之间的直线距离为宽,以两条竖直线段中较低一条线的高度作为高,形成一个水箱,求这些线段组成的水箱可容纳的最大面积是多少?

解法介绍

第一眼就想到了O(n*n)的暴力算法,果断放弃了这个算法,即使是去面试,这种算法肯定要被鄙视。于是我仔细想着有没有nlogn或者线性复杂度的方法,但是我想了很久,一直没有想到更好的办法。最后去百度了一下,看了别人的方法,豁然开朗,原来如此。
假设我们挑选了两条线段,高度分别为hi和hj,再假设hi是较矮的一条。hi所在的下标为i,hj所在的下标为j,不妨设j>i,于是这两条线段组成的水箱的面积为:
S = hi*(j-i),
假设S就是我们要求的最大面积,我们可以肯定下标j之后没有高度大于v[j]的线段,因为如果存在v[x]=hx>hj,那么S = hi*(x-i),很显然,x-i>j-i,同理可以证明,下标i的左边也没有比hi高的线段。

那么,知道这个有什么卵用呢?。。囧

  1. 我们从数组两边开始取数,此时形成的待选水箱长度是最长的,左边下标从i开始,右边下标从j开始,对应高度分别为hi和hj,再次假设hi小于hj,于是此时S=hi
    X(j-i),然后开始挑选下一跳待选线段,那么问题来了,选择++i开始–j呢?

  2. 如果选择++i,优先挪动高度较低的线段的下标,假设下标变为k,对应高度为hk,有两种情况,hk大于等于hj, 面积S1’ = hj X
    (j-k) 和 hk小于hj,面积 S2’= hk X(j-k),这两种情况下S1’和S2’都有大于S的可能性,即可能找到更大面积的水箱

  3. 如果选择–j,优先挪动高度较高的线段的下标,假设下标变为k,对应高度为hk,也有两种情况,hk大于=hi,面积S1’ =
    hi*(k-i) ,很显然S1’小于S,如果hk小于等于hi,面积S2’ = hk X (k-i)小于S
    ,可以看到这种情况下找到的面积始终都小于我们当前面积S,这种方法还找个卵子最大面积?

综上所述,每次挪动都必须挪动高度较低的那个线段所在的下标

代码如下:

int maxArea(vector<int>& height) {
    int i = 0, j = height.size()-1;
    if (i > j)
        return 0;
    int rslt = 0;
    int tmpMax = 0;
    while (i != j)
    {
        //求出最大面积
        if (height[i] < height[j])
        {
            tmpMax = height[i] * (j - i);
                ++i;
        }
        else 
        {
            tmpMax = height[j] * (j - i);
                --j;
        }
        //进行更新
        if (tmpMax > rslt)
            rslt = tmpMax;
    }
    return rslt;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值