Problem Definition:
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.
Solution: 使用两个游标分别从height数组的起止位置开始往里靠。令i=0,j=len(height)-1。
每次只移动其中一个游标:把对应高度较小的游标往里移。形式化表示:
if height[ i ]<height[ j ]
then i++
else
j--
用一个实例来演示:
下图中的圆圈表示中间省略了很多杠杠。
1)i,j分别位于两端。height[i]<height[j],图中蓝色虚线跨过的区域就是以 i 为左边界所能得到的最大区域。(以 i 为左边界的区域,其高最大也就height[i],j再往左移,既不会增加高,又会减小底边长度)
然而对于 j 所对应的杆子来说,它是被 i 所拖累的,它有潜能形成更大的区域。应该把 i 右移来寻找更大的以j为右边界的区域。当然 i 往右移后不一定能得到一个 i',j 之间的更大区域,但是有机会啊。(当 height[ i ]*(j-i)<(min(height[ i'],height[j])*(j-i')))
2)i右移一步以后。height[i]>height[j]。
3)j左移一步......
走到上图这个状态,可以发现节省了很多不必要的计算(相比于暴力破解):
1._比如没有计算 [0, 5]这个区域。因为已经计算过的[0, 6]覆盖了[0, 5];
2._比如不会再去计算[2, 6]。因为已经计算过的[1,6]覆盖了[2, 6]...
如此一直进行到 i>=j为止。
1 # @param {integer[]} height 2 # @return {integer} 3 def maxArea(height): 4 maxWater,i,j=0,0,len(height)-1 5 while i<j: 6 if height[i]<height[j]: 7 water=(j-i)*height[i] 8 i+=1 9 else: 10 water=(j-i)*height[j] 11 j-=1 12 maxWater=max(maxWater,water) 13 return maxWater