題目難度: Medium
原題描述:
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 and n is at least 2.
題目大意:
在平面直角座標系的x軸上對(1,0)到(n,0)這n個點作n條長度不同的垂直於x軸的線段,問取其中哪兩條線段與x軸形成的容器能裝最多的水?
解題思路:
很容易能想到當選定兩條線段時,能裝的最多水量爲(j-i)*min{ai, aj}。一開始看錯題了,以爲x軸座標的點是不等距的,但這不影響整體的思路。由於要求的結果是由兩部分相乘得到的,因此要令結果最大,則兩部分都應該儘量取最大,但是這兩部分並不是獨立的,而是相關聯的,因此並不能做到兩部分同時取最大。最直接的做法是遍歷兩兩線段,得出結果的最大值,但是這種做法的時間複雜度是O(n^2),顯然不夠好,直觀上看應該有更好的算法。
一開始我想到的是,對於一條給定的線段,如果其它線段都比這條線段長,則選擇離這條線段最遠的線段就能得到最大的面積,但是如果其他線段有的比這條線段短,結果又不確定了,這正是我苦惱的地方。後來參考別人的做法才知道,這道題的突破口在於,選擇最左和最右的兩條線段,對於較短的線段,和它形成最大面積的線段就是這兩條的另一條線段。把這個想通了,這道題就迎刃而解了。
時間複雜度分析:
由於解法是設置兩個指針分別指向最左和最右,然後再向中間移動直至遇上,因此只需掃描一遍數組,時間複雜度是O(n)。
以下是代碼:
int maxArea(int* height, int heightSize)
{
int ans = 0;
int i,j,minHeight,area;
for(i=0,j=heightSize-1 ; i<j ; ){
minHeight = (height[i]<height[j] ? height[i] : height[j]);
area = minHeight * (j-i);
ans = (ans>area ? ans : area);
while(height[i]<=minHeight && i<j)
++i;
while(height[j]<=minHeight && i<j)
--j;
}
return ans;
}