【leetcode】42. (Hard) Trapping Rain Water

本文深入探讨了积水计算中的双指针与单调栈两种算法,通过实例详细解析了每种算法的工作原理,以及如何在积水计算问题中高效地找出最大积水容量。

题目链接


解题思路1:
双指针

提交代码:

class Solution {
    public int trap(int[] height) {
    	int left=0,right=height.length-1,min,sum=0;
    	
    	while(left<right) {
    		min=height[left]<height[right]?height[left]:height[right];
    		
    		if(height[left]<height[right]) {
    			left++;
    			while(left<right&&height[left]<min)
    			sum+=min-height[left++];
    		}
    		else {
    			right--;
    			while(left<right&&height[right]<min)
    			sum+=min-height[right--];
    		}
    	}
    	return sum;
    }
}

运行结果:
在这里插入图片描述


解题思路2:
单调栈

我们从左到右遍历所有的柱子,使用栈来保存柱子的坐标,保存的标准如下:
当当前柱子高度低于栈顶坐标位置的高度,则将下一个柱子的坐标入栈;
当当前柱子高度高于栈顶坐标位置的高度,则将栈中的元素不断弹出(pop)直至坐标为栈顶元素数值的柱子高于当前柱子的高度。

即我们维护的是一个单调递减栈,同时柱子之间能积蓄的雨水是柱子之间坐标的差值减一

以例题中的柱子高度数组 [0,1,0,2,1,0,1,3,2,1,2,1] 为例,对计算的过程进行说明:

假设我们有一个栈stack=[] 初始情况下为空

坐标为0的柱子,高度为0,将坐标入栈:
stack=[0]
累计可积蓄雨水量为0

坐标为1的柱子,高度为1。
当前柱子高度高于坐标为栈顶的柱子高度(栈顶元素为0,坐标为0的柱子高度为0)
则stack出栈,能够积蓄的雨水量为1-0-1=0(柱子坐标的差值-1)
同时将当前的柱子坐标入栈:
stack=[1]
累计可以积蓄雨水量为0

坐标为2的柱子,高度为0,高度低于1,入栈:
stack=[1,2]
累计可积累雨水量为0

坐标为3的柱子,高度为2,弹出所有高度低于当前柱子的柱子坐标,同时将当前柱子坐标入栈:
stack=[3]
累计可积累雨水量为3-1-1=1

坐标为4的柱子,高度为1,入栈;
stack=[3,4]
累计可积蓄雨水量为1

坐标为5的柱子,高度为0,入栈:
stack=[3,4,5]
累计可积蓄雨水量为1

坐标为6的柱子,高度为1,弹出栈顶元素直至坐标为栈顶元素的柱子高度高于当前柱子:
stack=[3]
累计可积蓄雨水量为1+(6-4-1)=1+1=2

坐标为7的柱子,高度为3,出栈操作后,有:
stack=[7]
累计可积蓄的雨水量为2+(7-3-1)=2+3=5

坐标为8的柱子,高度为2,入栈:
stack=[7,8]
累计可积蓄雨水量为5

坐标为9的柱子高度为1,入栈:
stack=[7,8,9]
累计可积蓄雨水量为5

坐标为10的柱子高度为2,出栈:
stac=[7,10]
累计可积蓄雨水量为5+(10-8-1)=5+1=6

坐标为11的柱子高度为1,入栈:
stack=[7,10,11]
累计可积蓄雨水量为6

至此已经遍历完所有的柱子,同时可以得到累计的可积蓄雨水量为6

提交代码:

class Solution{
	public int trap(int[] height) {
		Stack<Integer> stack=new Stack<Integer>();
		
		int i=0,water=0;
		int left,base,depth;
		while(i<height.length) {
			
			if(stack.isEmpty()||height[stack.peek()]>height[i])
				stack.push(i++);
			else {
				base=stack.pop();
				
				if(!stack.isEmpty()) {
					left=stack.peek();
					depth=Math.min(height[left],height[i])-height[base];
					water+=depth*(i-left-1);
				}
			}
		}
		return water;
	}
}

运行结果:
在这里插入图片描述

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值