O(n)时间解决的面试题:Container with most water

leetcode11

   

问题描述

   

一个数组a[i]表示数轴上i的位置有一条高度为a[i]的竖直线段,把两条线段当作一个容器左右边的高度,问,哪两条线段组成的容器容积最大。

   

分析问题

   

本质是求i<jmax{min{a[i],a[j]}}*(j-i)

   

解决问题

   

用两头扫的方法,伪代码如下:

i=0,j=n-1,best=0;

i<j:

best=max(best,min{a[i],a[j]}*(j-i))

if(a[i]<a[j]) ++i

else --j;

   

这里有个问题就是为什么采取a左边小的时候左边下标++,右边小的时候右边下标--的策略,最终就一定能够得到最大的一个容积呢,也就是说这种策略为什么就能够扫过最优解呢,下面我们来证明它。

   

证明

   

证明的关键就在于我们假设一边已经到了最优解的一个边界,而另外一边还没到最优解,那么没到的那边高度一定比最优解中较低的边低。

   

为什么呢,关键在于x轴的宽度,因为另外一边还没到最优解,所以这个时候x轴的宽度一定比最优解时的宽度宽,而这个时候如果没到的那边高度还比最优解中较低的那边高,那么这个时候容积就是已经到最优解的那条边的高度乘上现在x轴的宽度,这个乘积已经大于最优解了。所以只能是没到的那边高度一定比最优解中较低的那边低。

   

算法实现

   

class Solution{

public:

int maxArea(vector<int>& height){

int best=0;

int n=height.size();

for(int i=0,j=n-1;i<j;){

best=max(best,min(height[i],height[j])*(j-i));

if(height[i]<height[j]){

i++;

}

else{

j--;

}

}

return best;

}

}

原文地址:https://www.cnblogs.com/keedor/p/4526357.html