zoukankan      html  css  js  c++  java
  • [ 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%,美滋滋。
    写着写着就没啥思路了,画图倒是一把好手!
    继续跪谢阎总带我算法入门,三四百没白交。

  • 相关阅读:
    c++之五谷杂粮4---explicit
    ping
    Swift常量和变量
    Swift数据类型简介
    Swift 注释
    Swift标示符以及关键字
    xcode简介
    认识Swift
    Android_adb详解
    详解Android AM命令
  • 原文地址:https://www.cnblogs.com/recoverableTi/p/12631619.html
Copyright © 2011-2022 走看看