題目描述
給你 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;
};
- 把計算面積提出到getArea中了
- 標記了start,end。並利用其進行剪枝(優化去掉不必要的for循環),因爲我們很容易看出來,比end(距離start最遠)位更短的木板沒有必要再進行計算了。
解題思路 二 雙指針
其實這道題的思路是這樣:
計算start,end之間的距離(寬),和Math.min(start,end)(高)的面積。
怎麼計算最大面積呢?目標是找最寬和最高。
即在start,end距離最遠的情況下,找兩邊最高的木板。
所以,我們通過讓start和end在最遠的距離處,開始慢慢靠近,靠近的規則是:
- 拋棄最短的,即若start比end處的木板短,start向右移一位+1,(反之end處短,則end - 1)
- 這樣可以使兩邊都保證是最長的木板之間的面積
- 同樣我們可以加入上面的優化,移位後,比原本位置短的,直接過濾掉。
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;
};