给定n个非负整数a1,a2,...,an,其中每个代表坐标(i,ai)处的一个点。绘制n条垂直线,使得线i的两个端点处于(i,ai)和(i,0)处。找到两条线,它们与x轴一起形成一个容器,使得容器包含最多的水。容器无法倾斜,n至少为2。
木桶效应,一个水桶装多少水取决于最短的木板,这是隐含条件。所以我们的最终运算结果应该是:
(high-low)*Math.min( height[low], height[high] ),即底部的长度,乘以两条边中较短一条的长度。
暴力搜索,从头到尾算出每一个组合的容积并进行比较。这种方法非常直观容易,但是明显效率很低,时间复杂度达到了n2
解决问题嘛,咱们还是尽可能想出最好的办法。水桶的壁长总在变化不太好控制,至少我们知道底盘越大,存的水总归越多。所以考虑在初始化的时候,给数组的首位和末尾各设置一个桶壁,从数组的上下界开始计算,然后逐渐收拢桶壁。
收拢的条件又是什么呢?在木桶底部不断缩小的前提下,感觉上舍弃当前两壁中较短的一个,才更有可能获得容积上的增益(在文末提出一点疑惑)。于是我们以当前两桶壁的比较为标准,舍弃较短的一面,并让这一面向内收拢。
贴代码:
public int maxArea(int[] height) {
if(height.length<2) return 0;
int low = 0, high = height.length-1;
int max = 0;
while(low<high) {
max = Math.max( max , (high-low) * Math.min(height[low], height[high]) );
if(height[low] < height[high]) {
low++;
}else high--;
}
return max;
}
在思考算法本身的时候,感觉到舍弃较长桶壁也是有可能得到增益,但是写程序就尽可能按照逻辑来。至于为什么一定能算出最优解,其实我也没想明白,但是在验算的时候设想了几种场景,按照这个算法都能得出正确结果。可能是数学上的某种逻辑吧?欢迎明白这个原理的朋友解释指正~