LeetCode每日一题 接雨水 动态规划

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
如图:
在这里插入图片描述
这道题的解法依旧很简单,我们可以搜索两个相同数列,取他的指标相加减,也可以从底部向上依次累加,寻找每一层会存续的水,我们依旧先看暴力解法是否可以完成。

暴力解法

在暴力解法之中,我们可以一层一层的搜索,将每一层可能蓄积的水都做出来,直到最高的的水位,原理较为简单,具体注释在代码中表明,时间复杂度为 O(n2),我们可以稍微简化一下,让第二次遍历不需要遍历全部列表,具体代码如下:

func trap(arr []int) int {
    output := 0
    //设定开始和结束量柱子,就能将最高水位确定好,排除掉单个高柱的情况
    start := 0
    end := 0
    //表明特殊值
    if len(arr)==0 || len(arr) == 1{
    		return 0
	}
	for k :=1;k<=Maxheight(arr);k++{
        start = Min(arr, k)
        end = Max(arr, k)
        for i:= start; i< end+1; i++{
            if arr[i] < k {
               output+=1
            }
        }
	}
    return unit
}
//找到最高的柱子
func Maxheight(arr []int)  int{
	max := arr[0]
	for i := 1; i < len(arr); i++ {
		if max< arr[i] {
		   max = arr[i]
		}
	}
	return maxVal
}
//找到最开始的能承接水位的位置
func Min(arr []int,aa int) int {
	index := 0
	for i := 0; i <len(arr); i++ {
		if arr[i] >= aa{
			index = i
			break
		}
	}
	return index
}
//找到最后能承接水的位置
func Max(arr []int,aa int) int {
	index := 0
	for i := 0; i < len(arr); i++ {
		if arr[i] <= aa{
			index = i
			break
		}
	}
	return index
}

动态规划

我们看之前的暴力解法,是否可以简化,事实上,原来的暴力算法在每一次提升的时候,都要遍历一遍数组,找到左右两边的水位值,能否对此进行优化,就是下一步算法要做的事情,做动态规划的前提,就是先了解暴力算法如何解,如果能用动态规划将所有水位记录下来,然后将这个水位与当前位置进行比对,就能得出此处是否有积水,积水多少,遍历一次即可结束。

由于对于每处的最高水位要看左右两个最高的水柱,所以我们可以左右各经历一次遍历,取其水位较小值和当然位置进行对比,具体算法模型如图推导:
假设有如图的水柱:
在这里插入图片描述
我们先从左到右按照最高水位来计量:
在这里插入图片描述
然后按照从右到左的方向,以同样方式计量:
在这里插入图片描述
然后在遍历时取到他们的最小值,两相结合就可以得到他们的最高水位:
在这里插入图片描述

具体代码如下:

func trap(height []int)int{
    if len(height)==0{
		return 0
	}
	size :=len(height)
	res :=0
	leftDP :=make([]int,size)
	rightDP :=make([]int,size)
	leftDP[0]= height[0]
	rightDP[size-1] = height[size-1]

	for i:=1;i<size;i++{
		leftDP[i] = max(leftDP[i-1],height[i])
	}
	for i:=size-2;i>=0;i--{
		rightDP[i] = max(rightDP[i+1],height[i])
	}
	for i:=1;i<size-1;i++{
		minHeight := min(leftDP[i],rightDP[i])
		waterVal :=minHeight-height[i]
		res +=waterVal
	}
	return res
}

func max(a,b int)int{
	if a>b{
		return a
	}
	return b
}
func min(a,b int)int{
	if a>b{
		return b
	}
	return a
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值