code第一部分:数组 第十四题 雨水问题

code第一部分:数组 第十四题 雨水问题

 

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
对于每个柱子,找到其左右两边最高的柱子,该柱子能容纳的面积就是 min(max_left,
max_right) - height。所以,
1. 从左往右扫描一遍,对于每个柱子,求取左边最大值;
2. 从右往左扫描一遍,对于每个柱子,求最大右值;
3. 再扫描一遍,把每个柱子的面积并累加。
第一种方案的时间复杂度O(N),空间复杂度为O(N);
 
解决方案2
1. 扫描一遍,找到最高的柱子,这个柱子将数组分为两半;
2. 处理左边一半;
3. 处理右边一半。
第二种方案的时间复杂度O(N),空间复杂度为O(1);
 
解决方案3
使用栈;用一个栈辅助,小于栈顶的元素压入,大于等于栈顶就把栈里所有小于或等于当
前值的元素全部出栈处理掉。
时间复杂度 O(n),空间复杂度 O(n)
#include <iostream>

#include <stack>

using namespace std;


int min(int n,int m)
{
    if (n>m)
    {
        return m;
    }
    else
        return n;
}

int water(int a[],int n)
{
    int i;
    const int count=n;
    int b[count];
    int c[count];
    int sum1=0;
    for (i = 1; i < count; i++)
    {
        if (a[i]>sum1)
        {
            sum1=a[i];
        }
        b[i]=sum1;
    }

    int j;
    int sum2=0;
    for (j = count-2; j >=0; j--)
    {
        if (a[j]>sum2)
        {
            sum2=a[j];
        }
        c[j]=sum2;
    }

    int sum=0;
    int k;
    for (k = 1; k < count-1; k++)
    {
        sum+=min(b[k],c[k])-a[k];
    }
    return sum;
}


int water2(int a[],int n)
{
    int i=0;
    int max=0;
    int pos=0;
    for (i = 0; i < n; i++)
    {
        if(a[i]>max)
        {
            max=a[i];
            pos=i;
        }
    }
    int j;
    int sum1=a[0];
    int ans=0;
    for (j = 1; j < pos; j++)
    {
        if (a[j]>=sum1)
        {
            sum1=a[j];
        }
        else
        {
            ans+=sum1-a[j];
        }
    }
    int sum2=a[n-1];
    int k;
    for (k = n-2; k>pos; k--)
    {
        if (a[k]>sum2)
        {
            sum2=a[k];
        }
        else
        {
            ans+=sum2-a[k];
        }
    }
    return ans;
}

int water3(int a[], int n)
{
    stack<pair<int, int>> s;
    int water = 0;
    for (int i = 0; i < n; ++i)
    {
        int height = 0;
        while (!s.empty())
        { // 将栈里比当前元素矮或等高的元素全部处理掉
        int bar = s.top().first;
        int pos = s.top().second;
        // bar, height, a[i] 三者夹成的凹陷
        water += (min(bar, a[i]) - height) * (i - pos - 1);
        height = bar;
        if (a[i] < bar) // 碰到了比当前元素高的,跳出循环
            break;
        else
            s.pop(); // 弹出栈顶,因为该元素处理完了,不再需要了
        }
        s.push(make_pair(a[i], i));
    }
    return water;
}



int main()
{
    int a[12]={0,1,0,2,1,0,1,3,2,1,2,1};
    int ans1=water(a,12);
    cout<<"ans1 is "<<ans1<<endl;

    int ans2=water2(a,12);
    cout<<"ans2 is "<<ans2<<endl;

    int ans3=water3(a,12);
    cout<<"ans3 is "<<ans3<<endl;
    return 0;
}

 

posted @ 2017-02-25 22:10  taoliu_alex  阅读(286)  评论(0编辑  收藏  举报