leetcode_11. 盛最多水的容器 (暴力遍歷=>雙指針)

題目描述

給你 n 個非負整數 a1,a2,…,an,每個數代表座標中的一個點 (i, ai) 。在座標內畫 n 條垂直線,垂直線 i 的兩個端點分別爲 (i, ai) 和 (i, 0)。找出其中的兩條線,使得它們與 x 軸共同構成的容器可以容納最多的水。

說明:你不能傾斜容器,且 n 的值至少爲 2。

解題思路 一暴力法

辦法一很簡單,雙層循環計算出所有可能的結果,選出最大的。



var maxArea = function(height) {
    let area = 0;
    for (let i = 0; i < height.length; i++) {
        for(let j = i; j < height.length; j++) {
            let m2 = Math.min(height[i],height[j]) * (j-i);
            if (m2 > area) {
                area = m2;
            }
        }
    }
    return area;
};

一點難度都沒有。

優化

接下來我們優化一下

var getArea = function(height, i, j){
    return Math.min(height[i],height[j]) * (j-i);
}
var maxArea = function(height) {
    let start = 0;
    let end = height.length - 1;
    let area = getArea(height, start, end );
    for (let i = 0; i < height.length; i++) {
        for(let j = height.length - 1; j > i; j--) {
            if (height[j] < height[end]) {
                continue;
            }
            if (area < getArea(height, i, j)) {
                area = getArea(height,i, j);
                start = i;
                end = j;
            }
        }
    }
    return area;
};
  1. 把計算面積提出到getArea中了
  2. 標記了start,end。並利用其進行剪枝(優化去掉不必要的for循環),因爲我們很容易看出來,比end(距離start最遠)位更短的木板沒有必要再進行計算了。

解題思路 二 雙指針

其實這道題的思路是這樣:
計算start,end之間的距離(寬),和Math.min(start,end)(高)的面積。
怎麼計算最大面積呢?目標是找最寬和最高。
即在start,end距離最遠的情況下,找兩邊最高的木板。

所以,我們通過讓start和end在最遠的距離處,開始慢慢靠近,靠近的規則是:

  1. 拋棄最短的,即若start比end處的木板短,start向右移一位+1,(反之end處短,則end - 1)
  2. 這樣可以使兩邊都保證是最長的木板之間的面積
  3. 同樣我們可以加入上面的優化,移位後,比原本位置短的,直接過濾掉。


var getArea = function(height, i, j){
    return Math.min(height[i],height[j]) * (j-i);
}
var maxArea = function(height) {
    let start = 0;
    let end = height.length - 1;
    let area = getArea(height, start, end );
    for (let i = 0,j = end; i < j;) {
            if (height[i] > height[j]) {
                j--;
                if (height[j] < height[end]) {
                    continue;
                }
            } else {
                i++
                if (height[i] < height[start]) {
                    continue;
                }
            }
            let m2 = getArea(height, i, j);
            if (area < m2) {
                area = m2;
                start = i;
                end = j;
            }
    }
    return area;
};

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