• [leetcode] Trapping Rain Water


    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;
        }
    };
  • 相关阅读:
    M1阶段的开发过程的一些反思
    Alpha版本发布说明
    Alpha版本BUG BASH
    Notes of Daily Scrum Meeting(11.19)
    Notes of Daily Scrum Meeting(11.17)
    Notes of Daily Scrum Meeting(11.15)
    Notes of Daily Scrum Meeting(11.14)
    flask_sqlalchemy介绍
    SQLAlchemy 简单笔记
    Python-3.6 安装pycrypto 2.6
  • 原文地址:https://www.cnblogs.com/hubavyn/p/4267468.html
走看看 - 开发者的网上家园