柱状图储水问题

题目:

给定一个数组,每个位置的值代表一个高度,那么整个数组可以看做是一个直方图,

如果把这个直方图当作容器的话,求这个容器能装多少水

例如:3,1,2,4

代表第一个位置高度为3,第二个位置高度为1,以此类推,这个直方图能装3格水。如图红色地方:


思路:很多人会误想到正出什么波峰波谷,这就从开始就错了,比如两个相邻的波峰之外还有更大的波峰,这么说来你中间这连个波峰波谷算的值多白算了,这个用直接点的想法来做就可以了,就找当前i位置上能装多少水,就是从i位置向前和后遍历,找到前后max值较小的减去当前i位置的值就是能装的水,当然要是前或后没找到i位置小的,那么就不能装水(给你5分钟画图理解下这个思想)。思路有了,考虑解法:

1、暴力解法,每个i位置,都前后遍历,这个方法的时间复杂度为O(n2),

2,空间换时间,预处理数组,在找i之前,定义一个0-i位置最大大值数组,做法就是右滑数组,再定义一个i-length-1的最大是数组,做法就是左滑数组,然后找i上能装的水时,不用前后找,只需要查表就可以,这个时间复杂度为O(n),空间复杂度为O(n)。

3、时间复杂度为O(n),空间复杂度为O(1),厉害了这个,想不想听,想不想学,定义一个左指针,指向第二个元素,一个有指针,指向倒数第二个元素,因为一个和最后一个肯定不能储水,设置左边最大值为arr[0],右边最大值为arr[arr.length-1],只需要判断左边最大值与右边最大值即可,当左边最大值小于右边最大值,左指针右滑,左指针位置上能装的水就是左边对大值减去左指针指的值,若左指针指向的值大于左边大值,就不减,说明不能储水,更新左边最大值,当右边最大值小于左边最大值时,右指针左滑,做法跟前类似,直到左指针小于等于有指针跳出循环。反正就一句话,哪边小那边指针移动,给你5分钟想想,我上代码了:

public static int getWater(int[] arr){
        if (arr == null || arr.length < 3) {
            return 0;
        }
        int value = 0;
        int leftMax = arr[0];
        int rightMax = arr[arr.length - 1];
        int l = 1;
        int r = arr.length - 2;
        while (l <= r) {
            if (leftMax <= rightMax) {
                value += Math.max(0, leftMax - arr[l]);
                leftMax = Math.max(leftMax, arr[l++]);
            } else {
                value += Math.max(0, rightMax - arr[r]);
                rightMax = Math.max(rightMax, arr[r--]);
            }
        }
        return value;
    }






  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值