zoukankan      html  css  js  c++  java
  • Leetcode: 43. 接雨水

    题目描述:

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

     

    上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 感谢 Marcos 贡献此图。

    示例:

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

    思路分析:

    思路一:这是一个类似木桶效应的问题。比较多的思路是利用单调栈来实现。之前大四上算法课的时候也做过类似的题目。维护一个单调递减的栈,当遇到大于当前栈顶的高度时,出栈,计算可接多少水,算法是取现在的栈顶元素与待进栈元素的较小高度减去这个出栈元素的高度,再乘上待进栈元素与栈顶元素的宽度。这里注意维护在栈内的元素时对应的下标,以保证能够求得正确的宽度。这个方法是逐层求可接雨水。时间复杂度为O(n^2)。

    思路二:

    在实际的面试过程中,肯定是希望能够优化这个算法,考虑用双指针,逐列的来取雨水。维护左右两个指针left和right,分别指向数组的头尾,同时维护两个数值,存maxleft和maxright,即当前遍历过的所有左右元素的最大高度。需要进行判断,若left的高度小于right的高度,则left++,否则right--。同时在每次判断是还需要多一次判断,即是否能够加水,需要判断当left小于right时,left是否小于maxleft,若是,那么就可以加水,所加的水为maxleft-height[left]。反之,当right小于等于left的高度时,添加maxright-height[right]的水量。这个方法的时间复杂度为O(n)。

    代码:

    思路一:

     1 class Solution {
     2 public:
     3     
     4     int trap(vector<int>& height) {
     5         if(height.size()==0)
     6             return 0;
     7         int sum_rain = 0;
     8         stack<int> s;
     9         for(int i=0; i<height.size(); i++)
    10         {
    11             if(s.empty() || height[i]<height[s.top()])
    12                 s.push(i);
    13             else
    14             {
    15                 while(!s.empty() && height[i]>height[s.top()])
    16                 {
    17                     int pre = s.top();
    18                     s.pop();
    19                     if(!s.empty())
    20                     {
    21                         sum_rain += (min(height[i], height[s.top()])-height[pre])*(i-s.top()-1);
    22                     }
    23                 }
    24                 s.push(i);
    25             }
    26         }
    27         return sum_rain;
    28     }
    29 };

    思路二:

     1 class Solution {
     2 public:
     3     int trap(vector<int>& height) {
     4         if(height.size()==0)
     5             return 0;
     6         int sum_rain = 0;
     7         int left=0, right = height.size()-1;
     8         int leftmax=0, rightmax=0;
     9         while(left<right)
    10         {
    11             if(height[left]<height[right])
    12             {
    13                 if(height[left]<leftmax)
    14                 {
    15                     sum_rain += (leftmax-height[left]);
    16                 }
    17                 else
    18                     leftmax = height[left];
    19                 left++;
    20             }
    21             else
    22             {
    23                 if(height[right]<rightmax)
    24                 {
    25                     sum_rain += (rightmax-height[right]);
    26                 }
    27                 else
    28                     rightmax = height[right];
    29                 right--;
    30                     
    31             }
    32             
    33         }
    34         return sum_rain;
    35     }
    36 };
  • 相关阅读:
    SQL语句实例学习汇总
    sql语句一些实用技巧for oracle
    无限级递归生成HTML示例及ListBox,DropDownList等无限树
    另类Sql语句直接导出表数据到Execl
    powerdesigner中sql脚本小写转大写,去双引号
    C#中利用jQuery获取Json值示例,Ajax方式。
    利用jquery解决下拉菜单被Div遮挡问题
    获取Textarea 元素当前的光标位置及document.selection.createRange()资料
    oracle中一些常用函数
    IE6 动态创建 iframe 无法显示的 bug,万恶的IE6
  • 原文地址:https://www.cnblogs.com/LJ-LJ/p/11166690.html
Copyright © 2011-2022 走看看