(棧)LeetCode42.接雨水

題目:
給定 n 個非負整數(shù)表示每個寬度為 1 的柱子的高度圖,計算按此排列的柱子,下雨之后能接多少雨水。


上面是由數(shù)組 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度圖,在這種情況下,可以接 6 個單位的雨水(藍色部分表示雨水)。 圖片來自力扣官網(wǎng)

解法一 暴力法
思路:
1、初始化ans = 0;
2、遍歷數(shù)組;
(1)遍歷該值左邊,找到左邊數(shù)組最大值
(2)遍歷該值右邊,找到右邊數(shù)組最大值
(3)取左右最大值的較小值,減去當前高度,累加到ans

var trap = function(height) {
    let ans = 0;
    for(let i = 1, len = height.length; i < len - 1; i ++){
        let left_max = 0, right_max = 0;
        for (let left = 0; left <= i; left ++){
            left_max = Math.max(left_max, height[left]);
        }
        for (let right = len - 1; right >= i; right --){
            right_max = Math.max(right_max, height[right]);
        }
        ans += Math.min(left_max, right_max) - height[i]
    }
    return ans;
};

解法二 動態(tài)規(guī)劃
思路:
1、基于以上遍歷尋找每個元素的左右最大值,可優(yōu)化為記錄從開端到當前位置為止的最大高度,從左右兩個順序開始;
2、遍歷數(shù)組,取當前位置上左右兩個最大值中較小的那個,減去當前高度,累加到ans;

var trap = function(height) {
    let ans = 0,
        len = height.length;
        left_max = [], 
        right_max = [];

    left_max[0] = height[0];
    right_max[len - 1] = height[len - 1];

    for (let i = 1; i < len; i ++){
        left_max[i] = Math.max(left_max[i - 1], height[i]);
    }
    for (let i = len - 2; i >= 0; i --){
        right_max[i] = Math.max(right_max[i + 1], height[i]);
    }
    for (let i = 1; i < len - 1; i ++){
        ans += Math.min(left_max[i], right_max[i]) - height[i];
    }
        
    return ans;
};

解法三 雙指針
思路:
在解法二的基礎(chǔ)上,優(yōu)化最大高度左右兩側(cè)較大的部分,將循環(huán)簡化為一次;
1、從左到右遍歷時,如果當前值比左側(cè)最大值大,則當前位置沒有雨水,更新最大值;如果比左側(cè)最大值小,則該位置會貯存雨水,雨水高度為左側(cè)最大值減去當前高度;
2、從右到左反之
過程參考下圖,圖片來源于力扣官網(wǎng)。

var trap = function(height) {
    let ans = 0,
        len = height.length;
        left = 0, 
        right = len - 1,
        left_max = right_max = 0;

    while(left < right){
        if(height[left] < height[right]){
            height[left] > left_max ? left_max = height[left] : ans += left_max - height[left];
            left ++;
        }else{
            height[right] > right_max ? right_max = height[right] : ans += right_max - height[right];
            right --;
        }
    }
   
    return ans;
};

解法四 棧
思路:
之前的思路都是累加每一列的雨水深度,該方法在每個水洼處逐行累加;
1、初始化一個棧
2、遍歷
(1)如果當前高度比棧頂元素小,將當前索引壓棧
(2)如果當前高度比棧頂元素大,彈出棧頂元素;記錄當前高度與彈出后棧頂索引對應(yīng)高度的最大值,減去當前被彈出的索引值,作為高度;計算當前索引與彈出后棧頂索引中間的距離,作為長度;計算長*高,累加到ans;重復(fù)(2)直到棧頂索引對應(yīng)高度大于等于當前高度

var trap = function(height){
    let ans = 0, current = 0;
    let stack = [];
    while (current < height.length) {
        while (!!stack.length && height[current] > height[stack[stack.length - 1]]) {
            let top = stack.pop();
            if (!stack.length)
                break;
            let distance = current - stack[stack.length - 1] - 1;
            let bounded_height = Math.min(height[current], height[stack[stack.length - 1]]) - height[top];
            ans += distance * bounded_height;
        }
        stack.push(current++);
    }
    return ans;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容