• [ Leetcode ] No.42 接雨水


    题目:
    给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

    示例:

    输入: [0,1,0,2,1,0,1,3,2,1,2,1]
    输出: 6
    

    解题思路:

    • 首先构建两个栈,h存高度,idx存下标。
    • 遍历数组,将height[i]h.top()做比较
      1. height[i] <= h.top(),则将对应的高度和下标都入栈。
      2. height[i] > h.top(),则表明可能可以求得面积。
        实际上,对于index = k的方块而言,可能接住的雨水等于 min(left, right) * width
        left 表示左边第一个比它高的柱子高度,right表示右边第一个比它高的柱子高度。
        width表示宽度。
      3. 之所以是可能可求得面积,是因为可求面积的重要条件是,左右两边都有柱子。
        而恰如题目给出的例子中,[1, 2]这样的情况下,index = 1的那个柱子是没办法接雨水的。
        因为没左边的柱子。这样的情况需要特殊判断。
    • 在求面积的时候,要一直退栈退到栈顶元素比height[i]大或者相等
    class Solution {
    public:
        int trap(vector<int>& height) {
            stack<int> h, idx;
            int sum = 0, tag = 0;
            int len = height.size();
            for(int i = 0; i < len; i++) {
                // 遍历到比栈尾还小的元素时,推入栈中
                if(h.empty() || h.top() >= height[i]) {
                    h.push(height[i]);
                    tag = 0;
                    idx.push(i);
                    continue;
                }
                while(h.top() < height[i]) {
                    int temp = h.top();
                    h.pop(), idx.pop();
                    if(!h.empty()) {
                        int left = h.top(), left_h = idx.top();
                        sum += (min(height[i], left) - temp) * (i - left_h - 1);
                    } else {
                        h.push(height[i]);
                        idx.push(i);
                        tag = 1;
                    }
                }
                // 栈顶只可能比当前height[i]更大或相等
                while(!h.empty() && tag == 0) {
                    if(h.top() == height[i]) {
                         h.pop(), idx.pop();
                         if(h.empty()) {
                            h.push(height[i]);
                            idx.push(i);
                            break;
                         }
                    } else {
                        h.push(height[i]);
                        idx.push(i);
                        break;
                    }
                }
            }
            return sum;
        }
    };
    
    

    心得:
    虽然今天心情烦躁,但是鉴于抓住了一点思路,就打算自己写写这题。
    因为之前看了不少关于单调队列、滑动窗口类型的题,感觉它们有点异曲同工的味道,很想尝试。
    接近三个小时都在接雨水,提交了4次,最后AC打败了94%,美滋滋。
    写着写着就没啥思路了,画图倒是一把好手!
    继续跪谢阎总带我算法入门,三四百没白交。

  • 相关阅读:
    POJ1087 A Plug for UNIX 网络流
    HDU4405 Aeroplane chess 期望DP
    POJ1062 昂贵的聘礼 区间枚举
    HDU4403 A very hard Aoshu problem 枚举
    HDU4407 Sum 容斥定理
    POJ2750 Potted Flower 线段树+DP
    软件项目开发流程以及人员职责
    10款最流行的开源Web设计工具
    C# 把\\r\\n替换为\r\n
    jquery validation 用到的输入验证正则表达式
  • 原文地址:https://www.cnblogs.com/recoverableTi/p/12631619.html
Copyright © 2020-2023  润新知