1. 程式人生 > 其它 >LeeCode( 動態程式設計)42_接雨水

LeeCode( 動態程式設計)42_接雨水

技術標籤:leetcode演算法動態規劃leetcodejava

LeeCode( 動態程式設計)42_接雨水

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

示例 1:
在這裡插入圖片描述

輸入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
輸出:6
解釋:上面是由陣列 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度圖,在這種情況下,可以接 6 個單位的雨水(藍色部分表示雨水)。
示例 2:

輸入:height = [4,2,0,3,2,5]
輸出:9

提示:

n == height.length
0 <= n <= 3 * 104

0 <= height[i] <= 105

來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/trapping-rain-water
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。

解題思路:
方法一:
暴力

  • 要想找到陣列每個座標能接的最大的雨水,只需要找到該點左右兩邊的最高值然後取這兩個最高值的最小值減去當前座標對應的值即可得到當前左邊可以接到的最大雨水。

Java程式碼:


public class 接雨水 {
	public int trap(int[] height) {
		int ans = 0;
		int
size = height.length; for(int i =1;i<size;i++){ int max_left = 0,max_right = 0; for(int j=i;j>=0;j--){ max_left = Math.max(max_left, height[j]); } for(int j=i;j<size;j++){ max_right = Math.max(max_right, height[j]); } ans+=Math.min(max_left, max_right)
-height[i]; } return ans; }

方法二:
動態程式設計

  • 此外可以在上面的基礎上進行優化,用動態程式設計的思想對程式碼進行修改

public class 接雨水 {
	public int trap(int[] height) {
		if(height == null || height.length == 0){
			return 0;
		}
		
		int ans = 0;
		
		int size = height.length;
		
		int left_max[] = new int[size];
		int right_max[] = new int[size];
		
		left_max[0] = height[0];
		
		for(int i=1;i<size;i++){
			left_max[i] = Math.max(left_max[i-1], height[i]);
		}
		
		right_max[size - 1] = height[size - 1];
		
	    for (int i = size - 2; i >= 0; i--) {
	        right_max[i] = Math.max(height[i], right_max[i + 1]);
	    }
	    
	    for (int i = 1; i < size - 1; i++) {
	        ans += Math.min(left_max[i], right_max[i]) - height[i];
	    }

	    return ans;
	}
}

方法三:

  • 我們通過維護一個棧,進行一次遍歷後便能計算出結果。
    用current表示當前的座標,當current小於棧頂元素時將current進行入棧操作(該處形成低窪),當遍歷到current大於棧頂元素時(即找到了低窪的兩個邊界)則做出棧操作並計算兩個邊界的距離並乘以當前座標的高度與兩個邊界高度最小值的差值得到低窪面積,最後加入答案ans。
import java.util.Deque;
import java.util.LinkedList;

public class 接雨水 {
	public int trap(int[] height) {
		int ans = 0,current = 0;
		Deque<Integer> stack  = new LinkedList<Integer>();
		
		while(current < height.length){
			while(!stack.isEmpty() && height[current] > height[stack.peek()]){
				int top = stack.pop();
				if(stack.isEmpty())
					break;
				int distance = current - stack.peek()-1;
				int dounded_height = Math.min(height[current], height[stack.peek()]) - height[top];
				ans += distance*dounded_height;
			}
			stack.push(current++);
		}
		
		return ans;
	}
}