【LeetCode】11. Container With Most Water(盛最多水的容器)-C++實現的三種方法
本題是Bloomberg的面試題。
問題描述:
一、第一種方法-暴力解法
當我們在面試時想不到解題的方法時,不妨使用暴力解法,雙重遍歷陣列。
當 i = 0 時,使用指標 j 遍歷陣列,找到第一輪的最大值 area:
當i = 2 ,使用指標 j 遍歷陣列,找到第二輪的最大值 area:
直到 指標 i 遍歷完成。
實現程式碼:
class Solution { public: int maxArea(vector<int>& height) { assert(height.size() >= 2); int area = 0; for(int i = 0 ; i < height.size() ; i ++) for(int j = i + 1; j < height.size() ; j ++) area = max(area , min(height[i], height[j]) * (j - i)); return area; } };
時間複雜度:O(n^2)
空間複雜度:O(1)
第二種方法:對撞指標法
分別在頭、尾元素定義兩個指標 l , r ;
如圖所示,遍歷陣列,直到兩個指標相遇,停止迴圈
實現程式碼:
/// Two Pointers /// Time Complexity: O(n) /// Space Complexity: O(1) class Solution { public: int maxArea(vector<int>& height) { assert(height.size() >= 2); int l = 0, r = height.size() - 1; int area = 0; while(l < r){ area = max(area , min(height[l], height[r]) * (r - l)); if(height[l] < height[r]) l ++; else r --; } return area; } };
第三種方法:對撞指標法的優化
首先,使用第一個和最後一行來評估最寬的容器。所有其他可能的容器都不那麼寬,所以要有更多的水,它們需要更高。因此,在評估了最寬的容器之後,在兩端都跳過不支援更高高度的線。然後評估我們到達的新容器。重複,直到不再有可能的容器。
實現程式碼:
int maxArea(vector<int>& height) { int water = 0; int i = 0, j = height.size() - 1; while (i < j) { int h = min(height[i], height[j]); water = max(water, (j - i) * h); while (height[i] <= h && i < j) i++; while (height[j] <= h && i < j) j--; } return water; }
分析:
① i = 0, j = 9
water = 1 * (9 - 0) = 9;
i ++; j 不變;
② i = 1, j = 8;
water = max(49, 7 * 7) = 49;
然後 j--;
③ i = 1, j = 7;
water = max(49, 3 * 6) = 49;
然後 j -- ;
④ i = 1, j =6;
water = max(49, 5 * 8) = 49;
然後 j -- ;
⑤ i = 2, j =5;
water = max(49, 3 * 4) = 49;
然後 j -- ;
⑥ i = 2, j =4;
water = max(49, 2 * 5) = 49;
然後 j -- ;
⑦ i = 2, j =3;
water = max(49, 2 * 1) = 49;
然後 j -- ;
兩個指標相遇,完成整個遍歷過程。
參考資料: