42. 接雨水

給定 n 個非負整數表示每個寬度爲 1 的柱子的高度圖,計算按此排列的柱子,下雨之後能接多少雨水。
在這裏插入圖片描述
上面是由數組 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度圖,在這種情況下,可以接 6 個單位的雨水(藍色部分表示雨水)。 感謝 Marcos 貢獻此圖。

示例:

輸入: [0,1,0,2,1,0,1,3,2,1,2,1]
輸出: 6

每次找出最高的柱子和第二高的柱子,得出它們之間能容納的雨水,然後通過遞歸得到左半部和右半部的結果相加就是所有的雨水了。

class Solution {
    public int trap(int[] height) {
        if(height==null || height.length == 0 || height.length == 1){
            return 0;
        }
        int start = 0;
        int end = height.length - 1;
        //去掉開頭的0
        while(height[start] == 0){
            start++;
        }
        //去掉末尾的0
        while(height[end] == 0){
            end --;
        }
        if(start +1 >= end){
            return 0;
        }
        return recursion(arraySub(height,start,end));
    }

    public int recursion(int[] res){
        int total = 0;
        int start = 0;
        int end = res.length - 1;
        for(int i = 1; i<res.length -1;i++){
            //得到res中最高的兩個柱子的座標
            if(res[i] > res[start] || res[i] > res[end]){
                if(res[start] > res[end]){
                    end = i;
                }else{
                    start = i;
                }
            }
        }
        //有可能出現end<start的情況
        if(start > end){
            int tmp = start;
            start = end;
            end = tmp;
        }
        //考慮兩個柱子相鄰的情況,就沒必要計算了
        if(start + 1 != end){
        	//取兩個柱子中較矮的那根
            if(res[start] > res[end]){
                total = res[end] * (end - start - 1);
            }else{
                total = res[start] * (end - start - 1);
            }
            //減去兩根柱子之間的那些柱子的高度就是結果
            for(int i = start + 1;i < end;i++){
                total -= res[i];
            }
        }
        //在start=1的情況下左子集必然只有兩根柱子,所以不用考慮
        if(start > 1){
            //求左子集的雨水
            total += recursion(arraySub(res,0,start));
        }
        if(end < res.length-2){
            //求右子集的雨水
            int[] newRes = new int[res.length - end];
            System.arraycopy(res,end,newRes,0,newRes.length);
            total += recursion(newRes);
        }
        return total;
    }

    public static int[] arraySub(int[] data,int start,int end){
        int[] C=new int[end-start+1];//新建數組C長度爲start-end
        for(int i=start,j=0;i<=end;i++,j++){
            C[j]=data[i];
        }
        return C;//返回截取數組的地址
    }

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