問題詳情
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(
因此我開始思考,水桶的裝水面積是由短的那條邊,乘以底邊,而我們需要找出裝水面積的最大值,那麼我們只需要考慮需要乘積的兩條邊的值。而其中底邊的最大值自然是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;
}
};