題目
題目.png
題意是說有n個非負的整數,他們分別以(i,ai)組成了n個點,每個點和(i,0)組成了垂直于x軸的直線,選取其中的兩條直線和X軸會組成一個凹槽,問凹槽能裝多少水。這題其實是求兩條直線和X軸能夠形成的最大面積,寬是兩個點之間X軸差的絕對值。高是兩個點中Y軸值最小的值。返回形成最大面積的值。
如下圖中的A點和H點(area=H*W=min(HA,HG)x(8-1)=1x7=7
分析
圖示.png
假設我們有上圖中圖示的點,該如何找滿足題意的兩條垂線呢?最簡單的就是窮舉所有的可能。任意選擇其中的兩條,求其中的最大值,但這樣會有很多多余的不必要計算。我們的思想是從兩邊往中間移動來計算最大的面積。
我們先假設有兩個索引點i和j,分別指向A點和H點。然后比較HA和HG,如果HA < HG則讓i往右移,指向B點,反之則讓j左移,指向G點。計算A和H形成的面積判斷是否更新原來的面積。剩余的點同理計算,直到i和j發生交叉。
這樣做能夠減少大量計算。如圖中的A和H兩個點。我們知道A點的高<H點的高,那么我們沒有必要再去計算A點去其他點形成的最大面積,因為A和H形成的寬度是最大的(這是為什么從兩端開始計算的原因,保證寬度最大),而A又是兩點之間最矮的,就是說A點與除了H點的其他點形成的面積是肯定小于和H點形成的面積(寬度小于H和A的寬度,高度最多小于等于A的高度)。這樣如果還有更大的面積形成,肯定是在除了A點以外剩余的點形成的,所以選擇移動i,將其指向B(保證寬度最大),在余下的點中找最大的面積。按照類似的思想計算下去,就能找到最大的面積。
代碼
代碼是java版,以C語言寫的話,應該會更快。
public class Solution
{
public int maxArea(int[] height)
{
int arrSize=height.length;
int max=0;
int i=0;
int j=arrSize-1;
while(i<j)
{
int area=(j-i)*(height[i]<height[j]?height[i]:height[j]);
max=area>max?area:max;
if(height[i]<height[j])
{
i++;
}
else
{
j--;
}
}
return max;
}
}