接雨水( LeetCode 42 )---栈 (Java)

请添加图片描述
请添加图片描述

package com.tang.project1.utils;

import java.util.Stack;

public class LeetCode42 {

    static class  Solution {
        public static int trap(int[] height) {
			//砖头的数目小于3都没法组成凹槽,没法装水,所以水的面积是0
            if(height.length < 3) return 0;

            Stack<Integer> stack = new Stack<>();
			//保存水的面积
            int res = 0;
			//遍历height数组
            for(int i = 0;i < height.length;i++){
            	//如果栈是空的,就可以将当前的数的数组下标压入栈中
                if(stack.isEmpty()){
                    stack.push(i);
                //如果将要压入的栈中的数,小于等于当前的栈顶元素,也将将当前的数的数组下标压入栈中
                }else if(height[i] <= height[stack.peek()]){
                    stack.push(i);
                }else{
                	//当栈中的值不为空,并且将要压入的栈中的数大于当前的栈顶元素
                    while(!stack.isEmpty()&&height[i] > height[stack.peek()]){
                    	//假如height[i]是下标为3的砖头
                    	//那么bottom就是下标为2的砖头
                        int bottom = stack.peek();
                        //把下标为2的砖头弹出栈中
                        stack.pop();
                        //此时栈中不为空,即凹槽的左侧存在元素
                        if(!stack.isEmpty()){
                        	//算出水的面积,先算出高,用左右两边高度最小的砖头高度减去底部的砖头,就可以得到水的高度,如上图下标为1的砖头和下标为3的砖头取高度较小的,减去下标为2的底部砖头
                        	//因为上面已经弹出了一块砖头,所以此时height[stack.peek()]是下标为1的砖头
                            int h = Math.min(height[i],height[stack.peek()]) - height[bottom];
                            //stack.peek()是下标为1的砖头,3 - 1 - 1,最后一个减1是,计算宽度都要减的。 
                            int w = i - stack.peek() - 1;
                            //res面积是累加的
                            res += h * w;
                        }
                    }
                    //用于比如第一个数是0 第二个数是1的情况,第一次循环0压入栈中,第二次循环,跳到else分支,在stack.pop()以后栈为空,但是此时1还是要入栈的,所以用stack.push(i);将1压入栈中
                    stack.push(i);
                }
            }
            //将结果返回
            return res;
        }
    }

    public static void main(String[] args) {
        int[] height = {0,1,0,2,1,0,1,3,2,1,2,1};
        System.out.println(Solution.trap(height));
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值