LeetCode 42. 接雨水

题目,leetcodeacwing

看这篇题解

算法1

(三次线性扫描)\(O(n)\)

每一列能储水的量,由该列左边最高的柱子,和该列右边最高的柱子决定。计算公式为\(V[i] = min(左边最高的柱子高度,右边最高的柱子高度)-height[i]\)

  1. 先线性扫描一遍,统计出每个柱子左边最高柱子的高度(这个最高的柱子有可能是自己)

  2. 再扫描一遍,统计出每个柱子右边最高柱子的高度

  3. 最后计算总的结果

时间复杂度

线性扫描三遍,所以是\(O(3n)\),也就是\(O(n)\)

空间复杂度

需要额外使用两个数组,\(O(n)\)

C++ 代码

class Solution {
public:
    int trap(vector<int>& height) {
        int n = height.size();
        if (!n) return 0;
        vector<int> left(n), right(n);

        left[0] = height[0];
        for (int i = 1; i < n; i ++)
            left[i] = max(left[i-1], height[i]);
        
        right[n-1] = height[n-1];
        for (int i = n-2; i >= 0; i --)
            right[i] = max(right[i+1], height[i]);
        
        int res = 0;
        for (int i = 0; i < n; i ++)
            res += min(left[i], right[i]) - height[i];
        
        return res;
    }
};

算法2

(单调栈)\(O(n)\)

对于每一个柱子,我们将其视为能够储水的凹槽的右边的柱子,去搜索在它左边能够构成凹槽的两个要素:一个比自己矮的柱子\(a\),和一个比\(a\)要高、在\(a\)左边的的柱子\(b\)。第一个要素我们可以在遍历的时候设定条件,第二个要素我们发现有这样的逆序关系:\(height[a] < height[b]\)但是\(a>b\),因此我们可以使用一个严格单调递减的单调栈来储存这些柱子。设单调栈为\(st\)

  1. 线性扫描,当要加入的柱子比栈顶元素st.top()高,则获取第一个要素,凹槽的底部,记作low_index然后出栈。
  2. 之后,假如栈不空的话,出栈之后的st​的栈顶元素st.top()​就是我们要找的第二个要素,凹槽的左侧,记作left_high_index
  3. 计算当前形成的凹槽容量,V = (i - left_high_index - 1) * (min(height[left_high_index], height[i]) - height[low_index])

时间复杂度

每个元素最多只会被入栈出栈一次,所以是\(O(n)\)

空间复杂度

额外使用了一个数组来维护单调栈,所以是\(O(n)\)

C++ 代码

class Solution {
public:
    int trap(vector<int>& height) {
        int n = height.size();
        if (!n) return 0;

        vector<int> st(n);
        int res = 0;
        for (int i = 0; i < n; i ++)
        {
            while(!st.empty() && height[i] >= height[st.back()])
            {
                int low_index = st.back();
                st.pop_back();
                if (st.empty()) break;
                int left_high_index = st.back();
                res += (i - left_high_index - 1) * (min(height[i], height[left_high_index]) - height[low_index]);
            }
            st.push_back(i);
        }
        return res;
    }
};
posted @ 2020-12-24 12:11  alexemey  阅读(67)  评论(0)    收藏  举报