前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >(Leetcode 2021 刷题计划) 面试题 17.21. 直方图的水量

(Leetcode 2021 刷题计划) 面试题 17.21. 直方图的水量

原创
作者头像
windism
修改2021-04-06 11:03:29
2890
修改2021-04-06 11:03:29
举报
文章被收录于专栏:风扬风扬

每日一题时间: 2020-04-02 题目链接: 面试题 17.21. 直方图的水量 官方题解链接: 直方图的水量

题目

给定一个直方图(也称柱状图),假设有人从上面源源不断地倒水,最后直方图能存多少水量?直方图的宽度为 1。

上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的直方图,在这种情况下,可以接 6 个单位的水(蓝色部分表示水)。

代码语言:txt
复制
示例:
输入: [0,1,0,2,1,0,1,3,2,1,2,1]
输出: 6

解题方法

解题思路: 首先应当考虑每个横坐标所能承载的水是由什么决定的? 接下来才能构建对应的算法。

每个点的水量是由其左边的直方图高点与右边直方图高点的最低值与当前的值的差值构成的

动态规划

解题思路: 已经知道数量的计算方法, 利用两个数组表示该点左边的高点以及右边的高点即可。

代码语言:txt
复制
class Solution {
public:
    int trap(vector<int>& height) {
        if(height.empty()) return 0;
        int n = height.size();
        vector<int> leftMax(n), rightMax(n);
        leftMax[0] = height[0];
        rightMax[n - 1] = height[n - 1];
        for (int i = 1; i < n; ++i) {
            leftMax[i] = max(leftMax[i - 1], height[i]);
        }
        for (int i = n - 2; i >= 0; --i) {
            rightMax[i] = max(rightMax[i + 1], height[i]);
        }

        int res = 0;
        for (int i = 0; i < n; ++i) {
            res += min(leftMax[i], rightMax[i]) - height[i];
        }
        return res;
    }
};
  • 复杂度分析
    • 时间复杂度: O(N)
    • 空间复杂度: O(N)

单调栈

解题思路: 动图请参考 直方图的水量

注意下面过程

代码语言:txt
复制
[2, 1, 0, 1, 3]
单调栈遇到index = 3时, 水量增加 1, 上式相当于 [2, 1, 1, 1, 3]
单调栈遇到index = 4时, 水量增加 3, 上式相当于 [2, 2, 2, 2, 3]

通过上面的变化可以看出: 单调栈是将其结果变为单调递增后单调递减数组

代码语言:txt
复制
class Solution {
public:
    int trap(vector<int>& height) {
        int res = 0, n = height.size();
        stack<int> stk;
        for (int i = 0; i < n; ++i) {
            while (!stk.empty() && height[i] > height[stk.top()]) {
                int top = stk.top();
                stk.pop();
                if (stk.empty()) {
                    break;
                }
                int left = stk.top();
                int curWidth = i - left - 1;
                int curHeight = min(height[left], height[i]) - height[top];
                res += curWidth * curHeight;
            }
            stk.push(i);
        }
        return ans;
    }
};
  • 复杂度分析
    • 时间复杂度: O(N)
    • 空间复杂度: O(N)

双指针

解题思路: 动图请参考 直方图的水量

当两个指针没有相遇是基于如下进行推断:

  • 使用 height[left]height[right] 的值更新 leftMaxrightMax 的值;
  • 如果 height[left]<height[right],则必有 leftMax<rightMax,下标 left 处能接的水的量等于 leftMax−height[left],将下标 left 处能接的水的量加到能接的水的总量,然后将 left1(即向右移动一位);
  • 如果 height[left]≥height[right],则必有 leftMax>=rightMax,下标 right 处能接的水的量等于 rightMax−height[right],将下标 right 处能接的水的量加到能接的水的总量,然后将 right1(即向左移动一位)。
代码语言:txt
复制
class Solution {
public:
    int trap(vector<int>& height) {
        int ans = 0;
        int left = 0, right = height.size() - 1;
        int leftMax = 0, rightMax = 0;
        while (left < right) {
            leftMax = max(leftMax, height[left]);
            rightMax = max(rightMax, height[right]);
            if (height[left] < height[right]) {
                ans += leftMax - height[left];
                ++left;
            } else {
                ans += rightMax - height[right];
                --right;
            }
        }
        return ans;
    }
};
  • 复杂度分析
    • 时间复杂度: O(N)
    • 空间复杂度: O(1)

参考资料

  1. 面试题 17.21. 直方图的水量
  2. 直方图的水量

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 题目
  • 解题方法
    • 动态规划
      • 单调栈
        • 双指针
        • 参考资料
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档