Container With Most Water

一. Container With Most Water

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.

Difficulty:Medium

TIME:30MIN

解法

這道題挺有意思的,題目的意思是x軸上有很多垂直的線段,問哪兩個線段和x軸可以形成一個容器,這個容器可以裝最多的水。也就是說雖然這個容器是一個梯形,但是如果水超過短的線段的話,水就會溢出來,因此說,這道題其實就是求短的線段和兩條垂直線之間的距離的面積。

弄明白意思之後立馬寫了一個O(n2) 的算法,就是對任意的兩個線段求一個面積,記錄面積的最大值,結果果真超時了(超時的數據有15000個樣例點)。

既然不能採用O(n2) 的算法,那麼需要尋找一種更加有效的算法。這道題既然就是求短的線段和兩條垂直線之間的距離的面積,那麼這個面積和兩樣東西有關,一樣是短的線段的長度,一樣是垂直線之間的距離,如果垂直線之間的距離最長而且短的線段長度最大的話,那麼面積當然是最大。

線段的長度是沒有規律的,但是線段之間的距離卻是有規律,相隔越遠,距離越大,那麼我們完全可以從兩端開始來查找最大的面積。令i 指向數組首部,j 指向數組末尾:

  • height[i]>=height[j] 的時候,面積就是(ji)height[j] ,這個時候j 向前移動變成j1
  • height[i]<height[j] 的時候,面積就是(ji)height[i] ,這個時候i 向前移動變成i+1

這樣遍歷一次就得到了最大的面積。

height[i]>=height[j] 的時候,爲什麼就一定是移動j 而不是移動i呢。其實可以這樣證明,如果移動i 變爲i+1 ,這個時候分兩種情況:

  • height[i+1]>=height[j] ,這個時候面積就是(ji1)height[j] ,顯然一定小於(ji)height[j]
  • height[i+1]<=height[j] ,這個時候面積就是(ji1)height[i+1] ,也顯然一定小於(ji)height[j]

所以不管怎樣移動i 都不會得到比(ji)height[j] 更優的結果,因此只能移動j ,當height[i]<height[j] 的時候也是類似的情況。因此這種方式一定能夠保證得到最大的面積。

int maxArea(vector<int>& height) {
    int i = 0,j = height.size() - 1;
    int result = 0;
    while(i <= j) {
        if(height[i] >= height[j]) {
            result = max(result, (j - i) * height[j]);
            j--;
        }
        else {
            result = max(result, (j - i) * height[i]);
            i++;
        }
    }
    return result;
}

代碼的時間複雜度爲O(n)

總結

這道題和之前做過一道題Two Sum很類似,雖然都可以用O(n2) 的暴力解法,但都能找到一種O(n) 的巧妙解法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章