zoukankan      html  css  js  c++  java
  • leetcode: Trapping Rain Water

    http://oj.leetcode.com/problems/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.
    
    The above elevation map is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped. Thanks Marcos for contributing this image!

     思路

    暴力方法肯定是能解决问题的,但是复杂度只能呵呵了。园子里转过一条新闻“面试题分析:我的Twitter技术面试失败了”,里面T社面试就是这题。我不能保证这个解法效率最优,但是复杂度可以通过OJ。基本原理就是找到其中一个个小的容器区间。需要两个堆栈和一个合并区间函数配合。第一个堆栈s1的类型为stack<pair<int, int> >,用来保存容器区间;第二个堆栈s2的类型为stack<int>,用来保存边界的位置。思路如下:

    1. 如果堆栈s2为空,把当前位置压入堆栈。
    2. 如果堆栈s2不为空:
      1. 如果栈顶所在位置的值大于当前位置的值,把当前位置压入堆栈。(A[i] < A[s2.top()])
      2. 如果前一条不满足,那么当前位置的值一定大于等于栈顶所在位置的值。(A[i] >= A[s2.top()])
        1. 如果堆栈s2不为空,并更新左边界位置为栈顶元素,如果左边界上的值大于当前位置的值,停止循环,不然弹出栈顶元素并继续比较。
        2. 将当前位置压入堆栈。
        3. 把当前元素所在位置压入堆栈。同时左边界和当前元素的位置正好构成一个容器区间,根据木板原理,容积由较小的值决定。如果s1不为空,栈顶元素可以和当前元素合并,弹出栈顶元素与当前区间合并,再继续循环检查栈顶元素,如果堆栈为空或者栈顶元素不能和当前区间合并,将当前元素压入堆栈。
    3. 遍历s1并计算容积。
     1 class Solution {
     2 public:
     3     bool isInRange(pair<int, int> &left, pair<int, int> &right) {
     4         return (left.first >= right.first) && (left.second <= right.second);
     5     }
     6     
     7     int getVolume(int A[], pair<int, int> range) {
     8         int left = range.first, right = range.second;
     9         int volume = min(A[left], A[right]) * (right - left - 1);
    10         
    11         for (int i = left + 1; i < right; ++i) {
    12             volume -= A[i];
    13         }
    14         
    15         return volume;
    16     }
    17     
    18     int trap(int A[], int n) {
    19         stack<pair<int, int> > ranges;
    20         stack<int> bars;
    21         
    22         for (int i = 0; i < n; ++i) {
    23             if (bars.empty()) {
    24                 bars.push(i);
    25             }
    26             else {
    27                 if (A[i] < A[bars.top()]) {
    28                     bars.push(i);
    29                 }
    30                 else {
    31                     int left;
    32                     pair<int, int> range;
    33                     
    34                     while (!bars.empty()) {
    35                         left = bars.top();
    36                         if (A[left] > A[i]) {
    37                             break;
    38                         }
    39                         
    40                         bars.pop();
    41                     }
    42                     
    43                     bars.push(i);
    44                     range.first = left;
    45                     range.second = i;
    46                     
    47                     while (!ranges.empty()) {
    48                         if (isInRange(ranges.top(), range)) {
    49                             ranges.pop();
    50                         }
    51                         else {
    52                             break;
    53                         }
    54                     }
    55                     
    56                     ranges.push(range);
    57                 }
    58             }
    59         }
    60         
    61         int volume = 0;
    62         
    63         while (!ranges.empty()) {
    64             volume += getVolume(A, ranges.top());
    65             ranges.pop();
    66         }
    67         
    68         return volume;
    69     }
    70 };
  • 相关阅读:
    C#磁吸屏幕窗体类库
    准备
    我写的诗
    How to turn off a laptop keyboard
    How to tell which commit a tag points to in Git?
    Why should I care about lightweight vs. annotated tags?
    How to get rid of “would clobber existing tag”
    Facebook, Google and Twitter threaten to leave Hong Kong over privacy law changes
    The need for legislative reform on secrecy orders
    Can a foreign key be NULL and/or duplicate?
  • 原文地址:https://www.cnblogs.com/panda_lin/p/trapping_rain_water.html
Copyright © 2011-2022 走看看