容器装水。最大装水量

给定一个数组代表一个容器, 比如[3,1,2,4], 

代表0位置是一个宽度为1,高度为3的直方图。

 代表1位置是一个宽度为1,高度为1的直方图。

 代表2位置是一个宽度为1,高度为2的直方图。

 代表3位置是一个宽度为1,高度为4的直方图。

 所有直方图的底部都在一条水平线上,且紧靠着。

 把这个图想象成一个容器,这个容器可以装3格的水。

 给定一个没有负数的数组arr,返回能装几格水?


分析,每个位置可以盛水的原理。


他们可以乘的水。就是左边最高的墙和右边最高的墙中 比较低的那个。 减去自己的高度

如果减后为负值。说明一点水都乘不了。↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓


分析的是每个位置可以盛的水

需要的数据是。每个位置。左边所有数组的最大值。右边所有数组的最大值。

使用预处理数组,保存结果

减少时间复杂度。计算总乘水量 时间复杂度O(N)

public static int getWater1(int[] arr){
		if (arr == null || arr.length < 3) {
			return 0;
		}
		int len = arr.length;
		//意义: 0 位置左边所有值中最大的。 1位值左边所有值中最大的。..
		int[] L = new int[len];
		//意义: 0 位置右边所有值中最大的。 1位值右边所有值中最大的。...
		int[] R = new int[len];
		
		L[0] = arr[0];
		for(int i=1;i<len;i++){
			L[i] = Math.max(arr[i],R[i-1]);
		}
		R[len-1] = arr[len-1];
		for(int i=len-2;i>=0;i--){
			R[i] = Math.max(R[i+1],arr[i]);
		}
		System.out.println(Arrays.toString(L));
		System.out.println(Arrays.toString(R));
		//利用原理和,需求数据求值
		//最前和最后不可能盛水
		int res = 0;
		for(int i=1;i<len-1;i++){
			//计算最短的墙。减去自己的高度
			int min = Math.min(L[i-1],R[i+1])-arr[i];
			res += min<0?0:min;
		}
		return res;
	}

分析预处理数组的值变化情况。和题意


最优解:

        public static int getWater2(int[] arr){
		if (arr == null || arr.length < 3) {
			return 0;
		}
		

		
		int res = 0;
		for(int l=0,r=arr.length-1;l+1<=r-1;){
			if(arr[l]<arr[r]){
				res += Math.max(0,arr[l]-arr[l+1]);//防止盛水量出现负数
				l++;
			}else if(arr[l]>arr[r]){
				res += Math.max(0,arr[r]-arr[r-1]);
				r--;
			}else{//墙高度相等,l和r谁变化都无所谓
				res += Math.max(0,arr[r]-arr[r-1]);
				r--;
			}
		}
		return res;
	}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SUNbrightness

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值