此题一开始看错了,后来才发现由小的一根(短板)决定高度。中间看过网上的解答,思路是O(n)的,略巧妙。其实就是基于这样一个直觉,先把L1设为最左,R1设为最右,这样宽度最大,然后缩小宽度,那么高度就要比原来高。缩小宽度的逻辑是,如果L1比R1小,那么L1往右移,否则反之。可以做简单证明。
如图,L1<R1<R2<L2,一开始面积有L1,R1和宽度决定,那么当向中间移动时,由于宽度减少,必然要增加一个高度。由于水位由较低的那一根(L1)决定,那么只有L1变到更高的L2才有可能起效果。移到中间的Lx没有作用,先移动R1也没有作用。
那么在L1移动到L2和R1移动到R2的过程中,存在的Lx和Rx都满足Lx < L1, Rx < R1。假设Lx < Rx,那么Lx* d(Rx - Lx) < L1*d(Rx-Lx) < L1 * ( R1 - L1)。若Lx > Rx,则Rx * d(Rx - Lx) < Rx * d(R1 - L1) < L1 * d(R1 - L1) (因为Rx,Lx都小于L1<R1)。直观的想就是,如果宽度减少,同时左右两侧的板都比原来的还要矮,怎么可能容纳更多的水呢?
所以画图还是很有用的。而且,一次过,爽。
public class Solution { public int maxArea(int[] height) { // Start typing your Java solution below // DO NOT write main() function int ans = 0; int tmp = 0; int l = 0; int r = height.length - 1; while (l < r) { int min = Math.min(height[l], height[r]); tmp = min * (r - l); if (tmp > ans) ans = tmp; if ( height[l] < height[r]) { int last = height[l]; while (l < r && height[l] <= last) { l++; } } else { int last = height[r]; while (l < r && height[r] <= last) { r--; } } } return ans; } }