zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    反悔贪心 学习笔记
    「CF901C」Bipartite Segments 题解
    「HEOI2015」公约数数列 题解
    拓展欧拉定理
    莫比乌斯反演题目选做
    八月水题录
    chapt15、使用虚拟内存
    chapt16、线程堆栈
    chapt14、探索虚拟内存
    get files version by vbs
  • 原文地址:https://www.cnblogs.com/tao-alex/p/6443035.html
Copyright © 2011-2022 走看看