算法分析與設計——LeetCode Problem.11 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.

題目已經給出了一個c++的框架

class Solution {
public:
    int maxArea(vector<int>& height) {

    }
};

問題分析與思路

題意是讓我們將一個vector數組想像成一個方形2d水桶,水桶以vector數組中的兩個數爲左右兩邊,以這兩個數在vector數組中的距離爲底。
這道題可以說一個剛學習c語言的人也能做出來,只需要使用c語言裏最基礎的冒泡算法,再查查vector的用法就能解決掉。

但是!

這裏有一個問題,冒泡算法的算法複雜度是O(n2 ),而這樣的算法複雜度用來解決這樣一道題在我看來十分浪費!
因此我開始思考,水桶的裝水面積是由短的那條邊,乘以底邊,而我們需要找出裝水面積的最大值,那麼我們只需要考慮需要乘積的兩條邊的值。而其中底邊的最大值自然是vector的大小減1。
因此我先從底邊最大開始考慮,讓底邊依次變小,這可以保證底邊的長度從最大到最小都能被考慮到,且底邊的兩個端點可能是vector中的任意兩個端點!
然後就考慮底邊如何變小的過程,由於我們的裝水面積是底邊乘以左右兩邊中小的那一個數,且每次端點變化時底邊長度減1,因此如果要讓後面的裝水面積有可能大於前面的裝水面積,我們必須留下左右兩邊中較大的那一個數!然後將左右兩邊較小的數的端點移動,使得底邊變小。
這個算法保證了底邊的端點可能是數組中任意兩個位置。同時底邊每次變小時都保留了較長邊,保證不會再次使用上次計算面積時的較小邊。因此他找出來的一定是最大面積。
以上是算法的核心思路。這樣從左右依次靠近的算法由於只遍歷了一次vector數組,因此他的時間複雜度是O(n)!比冒泡算法改進了太多了!


具體代碼

class Solution {
public:
    int maxArea(vector<int>& height) {
        int max = 0, LeftEdge = 0, RightEdge = height.size() - 1;
        int now = 0;
        while(LeftEdge != RightEdge) {
            if(height.at(LeftEdge) >= height.at(RightEdge)) {
                now = height.at(RightEdge) * (RightEdge - LeftEdge);
            }
            else {
                now = height.at(LeftEdge) * (RightEdge - LeftEdge);
            }
            if(max < now) {
                max = now;
            }
            if(height.at(LeftEdge) > height.at(RightEdge))RightEdge--;
            else LeftEdge++;
        }
        return max;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章