• [LeetCode] Trapping Rain Water II 题解


    题意

    题目

    思路

    我一开始想的时候只考虑到一个结点周围的边界的情况,并没有考虑到边界的高度其实影响到所有的结点盛水的高度。

    我们可以发现,中间是否能够盛水取决于边界是否足够高于里面的高度,所以这必然是一个从外到内,从小到大的一个过程。因为优先队列必然首先访问的是边界中最小的高度,如果周围小于这个高度那么必然是存在可以盛水的地方,就算是没有也没有任何的损失,只是更新了高度,但是队列依然会从高度小的结点开始访问;

    实现

    typedef struct node {
        int x, y;
        node(int x, int y) : x(x), y(y) {}
    } Node;
    
    class Solution {
    public:
        /**
         [1,4,3,1,3,2],
         [3,2,1,3,2,4],
         [2,3,3,2,3,1]
         发现:四条边都不可以存储水,,也就是在这个二维数组中才能存储水
         从第二列开始,去找四周里面大于它自己的第一个数(前提是三面或者两面是大于它的),然后减去自己
         */
        int trapRainWater(vector<vector<int>>& heightMap) {
            if (heightMap.size() == 0) {
                return 0;
            }
            else if (heightMap.size() < 3 || heightMap[0].size() < 3) {
                return 0;
            }
    
            int row = heightMap.size();
            int col = heightMap[0].size();
    
            queue<Node*> queues;
            vector<vector<int>> visited(row, vector<int>(col, 0));
    
            Node *start = new Node(1, 1);
    
            visited[1][1] = 1;
            queues.push(start);
    
            auto state_center = [&](int x, int y) {
                if (x >= 1 && x <= heightMap.size()-2 && y >= 1 && y <= heightMap[0].size()-2) {
                    return true;
                }
                return false;
            };
    
            //上下左右
            vector< vector<int>> layouts = {{1, 0}, {-1, 0}, {0, -1}, {0, 1}};
            int sum = 0;
    
            while (!queues.empty()) {
                Node* node = queues.front();
                queues.pop();
    
                // 取中间的值
                if (state_center(node->x, node->y)) {
                    vector<int> priority;
                    bool isfinished = true;
                    // 找周围四个点
                    for (int i = 0; i < layouts.size(); i++) {
                        vector<int> temp = layouts[i];
                        int newx = node->x + temp[0];
                        int newy = node->y + temp[1];
    
                        // 不符合条件
                        if (heightMap[newx][newy] > heightMap[node->x][node->y] && (newx == 0 || newx == heightMap.size()-1) &&
                                (newy == 0 || newy == heightMap[0].size()-1)) {
                            isfinished = false;
                            break;
                        }
                        else if (newx == 0 || newx == heightMap.size()-1 || newy == 0 || newy == heightMap[0].size()-1) {
                            priority.push_back(heightMap[newx][newy]);
                            continue;
                        }
    
                        Node *newnode = new Node(newx, newy);
                        if (!visited[newx][newy]) {
                            queues.push(newnode);
                            visited[newx][newy] = 1;
                        }
                    }
    
                    if (isfinished) {
                        sort(priority.begin(), priority.end());
                        int val = heightMap[node->x][node->y];
                        for (int i = 0; i < priority.size(); i++) {
                            if (priority[i] >= val) {
                                sum += priority[i] - val;
                                break;
                            }
                        }
                    }
                }
            }
    
            return sum;
        }
    
        /**
         * 存放水的高度取决于周围的最小高度,BFS的思想
         * 首先存取四面的高度,用优先队列去存储,保证取出来的一定是队列中的最小值
         * 取较大的高度,如果存在没访问过并且小于当前最小高度的,则计算盛水高度,并且将该结点设置成已访问
         *
         * @param heightMap
         * @return
         */
        int trapRainWater2(vector<vector<int>>& heightMap) {
            if (heightMap.size() == 0) {
                return 0;
            }
    
            int row = heightMap.size();
            int col = heightMap[0].size();
    
            struct cmp {
                bool operator()(pair<int, int> a, pair<int, int> b) {
                    if (a.first > b.first) {
                        return true;
                    }
                    else {
                        return false;
                    }
                }
            };
    
            priority_queue<pair<int, int>, vector<pair<int, int>>, cmp> queue;
            vector<vector<int>> visited(row, vector<int>(col, 0));
    
            // 将外围的高度加入到队列中,找出最小值
            for (int i = 0; i < row; i++) {
                for (int j = 0; j < col; j++) {
                    if (i == 0 || i == row-1 || j == 0 || j == col-1) {
                        queue.push(make_pair(heightMap[i][j], i * col + j));
                        visited[i][j] = 1;
                    }
                }
            }
    
            vector< vector<int>> layouts = {{1, 0}, {-1, 0}, {0, -1}, {0, 1}};
            int maxHeight = INT_MIN, sum = 0;
            while (!queue.empty()) {
                pair<int, int> content = queue.top();
                queue.pop();
    
                int height = content.first;
                int x = content.second / col;
                int y = content.second % col;
    
                maxHeight = max(maxHeight, height);
    
                for (auto temp : layouts) {
                    int newx = x + temp[0];
                    int newy = y + temp[1];
    
                    if (newx < 0 || newx >= row || newy < 0 || newy >= col || visited[newx][newy]) {
                        continue;
                    }
    
                    if (heightMap[newx][newy] < maxHeight) {
                        sum += maxHeight - heightMap[newx][newy];
                    }
    
                    visited[newx][newy] = 1;
                    queue.push(make_pair(heightMap[newx][newy], newx * col + newy));
                }
            }
    
            return sum;
        }
    
        void test() {
            vector< vector<int>> water = {
                    {12,13,1,12},
                    {13,4,13,12},
                    {13,8,10,12},
                    {12,13,12,12},
                    {13,13,13,13}
            };
            int result = this->trapRainWater2(water);
            cout << "sum:" << result << endl;
        }
    };
    
    

    参考文章

  • 相关阅读:
    centos7下vi的用法
    jQuery的hover方法搭配css的hover选择器,实现选中元素突出显示
    CSS3弹性伸缩布局(下)——flex布局
    什么是架构设计
    界面底部Tab实现
    一行代码实现圆形头像
    免费快速制作个人简历
    基于JS的问卷调查
    基于CSS的个人网页
    纯HTML课表
  • 原文地址:https://www.cnblogs.com/George1994/p/6592847.html
Copyright © 2020-2023  润新知