[leetcode] Trapping Rain Water

來源:互聯網
上載者:User

標籤:

Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining.

For example, 
Given [0,1,0,2,1,0,1,3,2,1,2,1], return 6.

                                  圖1

思路:1. 我通過觀察測試案例[0,1,0,2,1,0,1,3,2,1,2,1]和上面,發現蓄水的地方存在於子序列[1,0,2],[2,1,0,1,3],[2,1,2]的地方,這樣的子序列有個共同特點就是兩邊的資料大(想象成河的堤),中間的資料小(想象成河底的礁石或凸起)。

2. 通過1中的想法,我得到初步的解決方案: 首先可以直觀的看出,要想能蓄水,序列中至少需要3個數(兩邊高,中間低);然後設定兩個指標,指標i初始化為指向序列的第一個元素,指標j初始化為i+1,設序列(數組)名為num,從j開始,我期望找到第一個比num[i]大的數,如果j=i+1,那麼就是不能蓄水的,如序列起始位置的[0,1],這時我可以將i加1,這樣我就能找到第一個子序列[1,0,2],其中i指向1下標為1,j指向2,下標為3,河寬=j-i-1=3-1-1=1,河高為1,蓄水量為河寬*河高=1*1=1. 蓄完水怎麼辦,從圖

                    

1中可以直觀地看出,將i賦值為j,將j賦值為j+1,再重複上述步驟。我的思路可以概括為找河堤,然後蓄水,那麼問題來了,我們找到的第一個序列[1,0,2]中是沒有礁石的,換句話說,兩個較大的數(河堤)中間夾的都是0(河底是平的),這樣就可以按照河寬*河高的方法計算蓄水量,那麼像第二個序列[2,1,0,1,3],我從數值2為起點,找到了第一個比它大的數3作為另一個堤,這時的i(2的下標)是3,j(3的下標)是7,在不考慮礁石(num[i]和num[j]之間的非零值)的情況下,蓄水量應該是(7-3-1)*2=6,那麼礁石所佔據的面積怎麼減去呢,稍微觀察一下發現num[i]和num[j]之間的數的和就是礁石的總面積,所以考慮子序列[2,1,0,1,3]的蓄水量就是6-(1+0+1)=4. 

3. 到這裡問題貌似解決了,但是接著出現了這樣一個問題,對於num[i],我找第一個比num[i]大的數作為另一半河堤,上述兩個序列都是能找到的情況,如果接著第2步,這時我需要將i賦值為值3的下標也就是7,這時我往前找找不到比num[i]大的值怎麼辦,將i++可以解決圖1中的問題,於是,我寫成了下列代碼:

 

class Solution {public:    int trap(int A[], int n) {        if(n<=2) return 0;        int i=0,j,temp;        int result = 0;        while(i<n-2)        {            j=i+1;            temp=0;            while(A[j]<A[i]&&j<n)            {                temp += A[j];                j++;            }            if(j==i+1||j==n) //the next is bigger or no num bigger than A[i]            {                i++;            }else{                int length = j-i-1;                int height = min(A[i],A[j]);                int area = height*length;                area -= temp;                result += area;                i=j;            }        }        return result;    }};

4. 按照第3步中,我如果往前找,找不到比當前大的值,我的做法是直接丟棄當前值,但這樣是有問題的,因為要蓄水,只要有凹槽就行(兩邊大,中間小),不一定要找到比當前值大的值,比如序列[4,2,3],那麼當j==n的時候(沒有找到比num[i]大的值),取min(num[n-1],num[i])作為河高,(j-i-1)作為河寬,減去中間的礁石(temp)就可以呢?顯然不是,如果序列是[4,2,3,1]這樣做就不行,最後我想出的辦法是削堤,也就是當無法找到比num[i]大的值的時候,我就將num[i]減小至剩下的數中最大的值,如[4,2,3,1],我就將4變為3,問題得到解決。輸出如下代碼:

class Solution {public:    int trap(int A[], int n) {        if(n<=2) return 0;        int i=0,j,temp;        int result = 0;        while(i<n-2)        {            j=i+1;            temp=0;            int max = A[j];            while(A[j]<A[i]&&j<n)            {                if(A[j]>max) max = A[j];                temp += A[j];                j++;            }            if(j==i+1) //the next is bigger or no num bigger than A[i]            {                i++;            }else if(j==n){                A[i]=max;    // cut down A[i]            }else{                int length = j-i-1;                int height = A[i];                int area = height*length;                area -= temp;                result += area;                i=j;            }        }        return result;    }};

 

[leetcode] Trapping Rain Water

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.