zoukankan      html  css  js  c++  java
  • Leetcode 42

    接雨水这题可谓十分经典了。最近准备多做一些这种直方图相关的题目。

    单调栈

    首先看一下单调栈解法。

    int trap(vector<int>& height) {
        stack<int> st;
        int ans = 0;
        int i = 0;
        while(i < height.size()){
            while(!st.empty() && height[i] > height[st.top()]){
                int oritop = st.top();
                st.pop();
    
                if(st.empty()) break;
                int newtop = st.top();
                int fillHeight = min(height[i], height[newtop]) - height[oritop];
                int distance = i - newtop - 1;
                ans += distance * fillHeight;
            }
            st.push(i);
            i += 1;
        }
        return ans;
    }

    为什么说这是一个单调栈呢?因为在访问某个柱子之前,前面的柱子一定已经把小于它的那些柱子给 pop 掉了,只留下一个单调递减的栈。

     while(!st.empty() && height[i] > height[st.top()]) 

    所以当我们访问黄色柱子的时候,前面出现过的非单调柱子排列,已经在处理中被灌满水了。

    现在我们又遇到一个递增的情况,此时我们需要做的是,找出栈顶柱子(红色)和栈顶之下的柱子(绿色)。

     由于栈是单调递减的,因此绿色柱子的高度一定大于等于红色柱子

    所以黄色柱子和绿色柱子之间可以灌水(深色部分),灌到红色柱子的高度以上。

    当然,绿色柱子不一定大于黄色柱子的高度。这时我们就可以再次循环,填补到更高,直到栈满足了单调递减为止。

    注意,如果栈是空的话,说明没有承接的对手柱子了,那么也就不能灌水。(如图所示,框内的虚空水是无法灌入的。)

    双指针

    双指针法初看之下可能有点奇怪。啊,这也行?

    首先我们介绍一个朴素的方法。

    我们从左往右,每个柱子存储的虚空水高度记为其左边最高柱子。用蓝色记录。

    再从右往左,每个柱子存储的虚空水高度记为其右边最高柱子。用黄色记录。

    那么,此时着色为绿色的部分,就是实际存储的水。

    编程中我们可以记录黄色虚空水和蓝色虚空水的高度,取其小值。

    观察这个方法,我们发现,虚空水为什么不能变成实水?是因为我们并不知道另一边是否有对手柱子承接虚空水。

    双指针法的原理就是,我们可以知道另一边至少存在一个柱子,使得我们的虚空水一定会被接住,变成实际的水

    例如,我们的右边指针指向蓝色柱子,左边指针指向黄色柱子。在这两根柱子之间有一根更高的柱子。

    当前,我们并不知道灰色柱子的存在。但是,至少我们知道,如果我们以蓝色柱子的高度从左向右填水,那么总会遇到一个柱子可以围挡起来。

    当然,当我们移动到了灰色柱子的位置,移动的指针就变成了右边。

    总之,以此类推。

    int trap(vector<int>& height) {
        if(height.size() == 0) return 0;
        int ans = 0;
        int left = 0, right = height.size() - 1;
        int leftmax = height[left], rightmax = height[right];
        while(left < right){
            if(height[left] < height[right]){
                if(height[left] >= leftmax){
                    leftmax = height[left];
                }
                else{
                    ans += leftmax - height[left];
                }
                left++;
            }
            else{
                if(height[right] >= rightmax){
                    rightmax = height[right];
                }
                else{
                    ans += rightmax - height[right];
                }
                right--;
            }
        }
        return ans;
    }
  • 相关阅读:
    949. Largest Time for Given Digits
    450. Delete Node in a BST
    983. Minimum Cost For Tickets
    16. 3Sum Closest java solutions
    73. Set Matrix Zeroes java solutions
    347. Top K Frequent Elements java solutions
    215. Kth Largest Element in an Array java solutions
    75. Sort Colors java solutions
    38. Count and Say java solutions
    371. Sum of Two Integers java solutions
  • 原文地址:https://www.cnblogs.com/KakagouLT/p/13693952.html
Copyright © 2011-2022 走看看