Trapping Water & 2D trapping 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.

左右两边开始往中间靠拢。

  • 如果左端最大值比右端最大值小,左边挪动。
  • 否则右侧往中间挪动。

虽然我一直以来解决方案曾经都是用stack做的,但是写的代码真的挺长,不是最优的。

class Solution {
public:
    int trap(vector<int>& height) {
        if(height.size()<=2)return 0;

        int l=0,r=height.size()-1;

        int leftMost=height[l],rightMost=height[r];

        int total=0;
        while(l<=r)
        {
            if(leftMost<rightMost)
            {
                int cur=min(leftMost,rightMost)-height[l];
                total+=max(cur,0);
                leftMost=max(leftMost,height[l++]);
            }
            else
            {
                int cur=min(leftMost,rightMost)-height[r];
                total+=max(cur,0);
                rightMost=max(rightMost,height[r--]);
            }
        }

        return total;
    }
};

二维的trapping rain water

解法来自http://www.cnblogs.com/deofly/p/trapping-rain-water-ii.html

Description: Given n x m non-negative integers representing an elevation map 2d where the area of each cell is 1 x 1, compute how much water it is able to trap after raining.

Example Given 5*4 matrix

[12,13,0,12] [13,4,13,12] [13,8,10,12] [12,13,12,12] [13,13,13,13] return 14.

  • 用优先级队列维护,每次出队列都是出当前队列中最小高度的,因此可以保证是其高的减去它。
  • 加入队列的时候,是用其周围高点作为其高度加入队列中。

    struct Node
    {
       int hi, wi, val;
       Node(int _hi, int _wi, int _val)
       {
           hi = _hi, wi = _wi, val = _val;
       }
    };
    
    struct Compare
    {
       bool operator()(Node n1, Node n2)
       {
           return n1.val>n2.val;
       }
    };
    
    class Solution
    {
    public:
       int getTrappingWater(vector<vector<int>> &m)
       {
           int h = m.size();
           int w = m[0].size();
           if (h<3 || w<3)return 0;
    
           priority_queue<Node, vector<Node>, Compare> que;
    
           vector<vector<bool>> visited(h, vector<bool>(w, false));
    
           for (int hi = 0; hi<h; hi++)
           {
               que.push(Node(hi, 0, m[hi][0]));
    
               visited[hi][0] = true;
               que.push(Node(hi, w - 1, m[hi][w - 1]));
    
               visited[hi][w - 1] = true;
           }
    
           for (int wi = 1; wi<w - 1; wi++)
           {
               que.push(Node(0, wi, m[0][wi]));
               visited[0][wi] = true;
               que.push(Node(h - 1, wi, m[h - 1][wi]));
               visited[h - 1][wi] = true;
           }
    
           int total = 0;
           while (!que.empty())
           {
               Node top = que.top();
               que.pop();
               if (top.hi>1 && !visited[top.hi - 1][top.wi])
               {
                   total += max(-m[top.hi - 1][top.wi] + top.val, 0);
    
                   visited[top.hi - 1][top.wi] = true;
    
                   que.push(Node(top.hi - 1, top.wi, max(m[top.hi - 1][top.wi], top.val)));
               }
    
               if (top.hi<h - 1 && !visited[top.hi + 1][top.wi])
               {
                   total += max(-m[top.hi + 1][top.wi] + top.val, 0);
    
                   visited[top.hi + 1][top.wi] = true;
                   que.push(Node(top.hi + 1, top.wi, max(m[top.hi + 1][top.wi], top.val)));
               }
    
               if (top.wi>1 && !visited[top.hi][top.wi - 1])
               {
                   total += max(-m[top.hi][top.wi - 1] + top.val, 0);
                   visited[top.hi ][top.wi - 1] = true;
    
                   que.push(Node(top.hi, top.wi - 1, max(m[top.hi][top.wi - 1], top.val)));
               }
    
               if (top.wi<w - 1 && !visited[top.hi][top.wi + 1])
               {
                   total += max(-m[top.hi][top.wi + 1] + top.val, 0);
                   visited[top.hi][top.wi+1] = true;
    
                   que.push(Node(top.hi, top.wi + 1, max(m[top.hi][top.wi + 1], top.val)));
               }
           }
           return total;
       }
    };
    

没有找到OJ,写了一个错误的解决方案!!

  • 首先找到down可以包围的最大值,O(n*m)
  • 遍历每一行,每一行类似一维从两端开始遍历。
  • 记录从第一行开始到当前的垂直方向最大值。

对于 [12,13,0,12] [13,4,13,12] [13,8,10,12] [12,13,12,12] [13,13,13,13]

情况来说,(1,1)点不仅是有其上下左右确定的,同时可能流到(2,1)->(2,2)->(2,3),所以其最大值是12

int getMostWater(vector<vector<int>> &m)
{
    int h=m.size(),w=m[0].size();

    if(h<3 || w<3)return 0;

    vector<vector<int>> down(h,vector<int>(w));

    for(int hi=h-2;hi>=0;hi--)
    {
        for(int wi=0;wi<w;wi++)
        {
            down[hi][wi]=max(down[hi+1][wi],m[hi+1][wi]);
        }
    }

    vector<int> up(w);
    int total=0;
    for(int hi=1;hi<hi-1;hi++)
    {
        for(int wi=0;wi<w;wi++)
        {
            up[wi]=max(up[wi],m[hi-1][wi]);
        }

        int l=0,r=w-1;
        int leftMost=m[hi][0],rightMost=m[hi][r];

        while(l<=r)
        {
            if(leftMost<rightMost)
            {
                int cur=min(leftMost,min(up[l],down[hi][l]))-m[hi][l];
                total+=max(cur,0);

                leftMost=max(leftMost,m[hi][l]);
            }
            else
            {
                int cur=min(rightMost,min(up[r],down[hi][r]))-m[hi][r];
                total+=max(cur,0);

                rightMost=max(leftMost,m[hi][r]);
            }
        }
    }

    return total;
}

results matching ""

    No results matching ""