其他分享
首页 > 其他分享> > Leetcode-面试题17.21 直方图的水量

Leetcode-面试题17.21 直方图的水量

作者:互联网

动态规划——用空间换时间
明确思路:对于下标 i,水能到达的最大高度等于下标 i 两边的最大高度的最小值,下标 i 处能接的水的量等于下标 i 处的水能到达的最大高度减去 height[i]
时间复杂度:O(n)
空间复杂度:O(n)

class Solution {
public:
    int trap(vector<int>& height) {
        int n=height.size();
        if(n==0){
            return 0;
        }
        //使用两个向量存储每个位置两边的最大高度
        vector<int> leftmax(n),rightmax(n);
        leftmax[0]=height[0];
        //正向遍历获得leftmax的值
        for(int i=1;i<n;i++){
            leftmax[i]=leftmax[i-1];
            if(height[i]>leftmax[i]){
                leftmax[i]=height[i];
            }
        }
        rightmax[n-1]=height[n-1];
        //逆向遍历获得rightmax的值
        for(int i=n-2;i>=0;i--){
            rightmax[i]=rightmax[i+1];
            if(height[i]>rightmax[i]){
                rightmax[i]=height[i];
            }
        }
        int ans=0;
        //计算每个位置的储水量
        for(int i=0;i<n;i++){
            ans+=min(leftmax[i],rightmax[i])-height[i];
        }
        return ans;
    }
};

单调栈
让栈保持递减存储,可以肯定栈底一定是栈中的最大值,stack[0]永远是最大值
每次向后读一个数据,若比栈顶元素小直接压栈,反之准备盛水
栈中所有小于当前数据的元素,都要与当前数据增长到同等高度,弹栈,增长的高度用水填满
时间复杂度:O(n)
空间复杂度:O(n)

class Solution {
public:
    int trap(vector<int>& height) {
        int ans=0;
        int 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();//栈顶元素top下面一个必是left,且高度一定低于left,若新节点高度高于top,必可得到一个接水区域
                stk.pop();//弹栈
                if(stk.empty()){
                    break;
                }
                int left=stk.top();
                int currwidth=i-left-1;//注意下计算细节
                int currheight=min(height[left], height[i])-height[top];//当前节点和左边节点的高度最小值-中间弹栈节点高度
                ans += currwidth * currheight;
            }
            stk.push(i);
        }
        return ans;
    }
};

双指针

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+=rightMax-height[right];
                right--;
            }else{
            	//同上
                ans+=leftMax-height[left];
                left++;
            }
        }
        return ans;
    }
};

标签:leftmax,面试题,rightmax,17.21,height,int,直方图,ans,left
来源: https://blog.csdn.net/qq_43699254/article/details/115412586