LeetCode-42-接雨水

在这里插入图片描述

1、单调栈

考虑到接雨水的特点,我们实质上能够接住雨水的是这样一个部分:在前半部分这个柱子的高度都是递减的,直到最后一个柱子 的高度超过了前半部分中最后一个柱子的高度,这个时候我们计算被超过的柱子上到其两侧较矮柱子的水量,并以此方法遍历整个数组。

基于以上计算水量的方法,我们可以考虑使用单调栈进行处理。虽然栈是一个先进后出的结构,但我们可以通过比较栈顶元素和下一位元素之间的大小关系,栈顶元素小则将其出栈直至栈顶元素大于下一位元素,然后再将下一位元素进栈,这样我们就可以确保栈中的数字都是递增或递减的。因此单调栈只处理Next Greater Element问题,即给你一个数组,返回一个等长的数组,对应索引存储着下一个更大元素,如果没有更大的元素,就存 -1。

基于以上的分析,我们可以设计代码如下:首先从数组开始位置进行遍历,若此时单调栈不为空且栈顶元素的高度小于下一个位置的高度则说明此时出现了一个高于栈中最后一个柱子的新柱子,因此需要计算此时最后一个柱子上方的水量。首先记录此时栈顶元素的下标并出栈,若出栈之后栈为空,说明此时左侧不再有柱子肯定接不了水,因此跳出循环。否则计算出栈元素的高度并与两侧柱子高度中的较小值进行比较计算这一层的水量。循环结束之后将新元素入栈并重复上述操作。

class Solution {
public:
    int trap(vector<int> &height) {
        int ans = 0;
        stack<int> st;
        for (int i = 0; i < height.size(); i++)
        {
            while (!st.empty() && height[st.top()] < height[i])
            {
                int cur = st.top();
                st.pop();
                if (st.empty()) break;
                int l = st.top();
                int r = i;
                int h = min(height[r], height[l]) - height[cur];
                ans += (r - l - 1) * h;
            }
            st.push(i);
        }
        return ans;
    }
};

2、动态规划法

在这里插入图片描述
显然,leftMax[0]=height[0],leftMax[0]=height[0],rightMax[n-1]=height[n-1],rightMax[n−1]=height[n−1]。两个数组的其余元素的计算如下:
当 1 <= i <= n−1 时,leftMax[i]=max(eftMax[i-1],height[i]);
当 0 <= i <= n-2 时,rightMax[i]=max(rightMx[i+1], height[i])。

class Solution {
    public int trap(int[] height) {
        int n = height.length;
        if (n == 0) {
            return 0;
        }

        int[] leftMax = new int[n];
        leftMax[0] = height[0];
        for (int i = 1; i < n; ++i) {
            leftMax[i] = Math.max(leftMax[i - 1], height[i]);
        }

        int[] rightMax = new int[n];
        rightMax[n - 1] = height[n - 1];
        for (int i = n - 2; i >= 0; --i) {
            rightMax[i] = Math.max(rightMax[i + 1], height[i]);
        }

        int ans = 0;
        for (int i = 0; i < n; ++i) {
            ans += Math.min(leftMax[i], rightMax[i]) - height[i];
        }
        return ans;
    }
}

3、双指针

双指针法是在动态规划法的基础上进行改进,从而降低了空间复杂度。注意到下标 i 处能接的雨水量由 leftMax[i] 和 rightMax[i] 中的最小值决定。数组 leftMax 是从左往右计算,数组 rightMax 是从右往左计算。

1、当两个指针未相遇时,移动left和right更新 leftMax 和 rightMax 的值;
2、如果 height[left] < height[right],则必有 leftMax < rightMax,下标 left 处能接的雨水量等于 leftMax - height[left],将下标 left 处能接的雨水量加到能接的雨水总量,然后将 \textit{left}left 加 11(即向右移动一位;
3、如果 height[left] >= height[right],则必有 leftMax >= rightMax,下标 right 处能接的雨水量等于 rightMax - height[right],将下标 right 处能接的雨水量加到能接的雨水总量,然后将 right 减 1(即向左移动一位。

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;
    }
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LeetCode-Editor是一种在线编码工具,它提供了一个用户友好的界面编写和运行代码。在使用LeetCode-Editor时,有时候会出现乱码的问题。 乱码的原因可能是由于编码格式不兼容或者编码错误导致的。在这种情况下,我们可以尝试以下几种解决方法: 1. 检查文件编码格式:首先,我们可以检查所编辑的文件的编码格式。通常来说,常用的编码格式有UTF-8和ASCII等。我们可以将编码格式更改为正确的格式。在LeetCode-Editor中,可以通过界面设置或编辑器设置来更改编码格式。 2. 使用正确的字符集:如果乱码是由于使用了不同的字符集导致的,我们可以尝试更改使用正确的字符集。常见的字符集如Unicode或者UTF-8等。在LeetCode-Editor中,可以在编辑器中选择正确的字符集。 3. 使用合适的编辑器:有时候,乱码问题可能与LeetCode-Editor自身相关。我们可以尝试使用其他编码工具,如Text Editor、Sublime Text或者IDE,看是否能够解决乱码问题。 4. 查找特殊字符:如果乱码问题只出现在某些特殊字符上,我们可以尝试找到并替换这些字符。通过仔细检查代码,我们可以找到导致乱码的特定字符,并进行修正或替换。 总之,解决LeetCode-Editor乱码问题的方法有很多。根据具体情况,我们可以尝试更改文件编码格式、使用正确的字符集、更换编辑器或者查找并替换特殊字符等方法来解决这个问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值