算法27-二维接雨水(最小堆)

题目:

矩阵的值代表这一点的高度,不同的高度会形成湖,求给定的一个矩阵能接多少的雨水

分析:

t1:=[]int{8,8,8,8,8,8,8,8}
t2:=[]int{8,9,1,2,1,4,5,8}
t3:=[]int{8,7,1,1,3,2,6,8}
t4:=[]int{8,6,1,2,5,7,2,8}
t5:=[]int{8,1,3,5,1,2,1,8}
t6:=[]int{8,7,9,2,1,4,6,8}
t7:=[]int{8,8,8,8,5,8,8,8}

与之前的岛的问题类似,我们需要知道有哪些湖,湖的边缘的最低点在哪

整个矩阵实际是一个大的湖,内部有无数的小湖泊,

实现:
在这里插入图片描述

1 每一个节点,记录value值,和在矩阵中的坐标

type Node struct{
	value int
	row int 
	col int
}

2 /实现一个最小堆

type Heap struct {
	Size int//index  len-1
	Elems []Node
}

3 用一个bool类型的数组记录节点是否在堆中

IsEnter:=[][]bool{}

4 把外围的数据加载到堆
先push行,并在isenter标记true
再push列,更新isenter

5 开始从堆顶弹出最小值,通过坐标找到它的上下左右,没在堆中就加入堆

初始化一个max值,每次弹出的值大于max就更新
加入堆的时候计算它能接收的水量,max减去弹出的节点的值,结果小于0就置为0
同时更新isenter
直到堆中元素为0,计算完所有水量

代码:

package main

import (
	"fmt"
	"math"
	// "sort"
	// "time"
)


type Node struct{
	value int
	row int 
	col int
}

type Heap struct {
	Size int//index  len-1
	Elems []Node
}

func NewHead(maxSize int) *Heap {
	//minheap := new(Heap)
	//minheap.Elems = make([]int, maxSize, maxSize)
	//return minheap
	minheap := Heap{Size: -1, Elems: make([]Node, maxSize, maxSize)}
	return &minheap
}

func (h *Heap) Push(x Node)  {
	if h.Size == len(h.Elems) - 1 {
		return
	}
	
	h.Size++
	i := h.Size
	// 与父节点进行比较,如果小于父节点,则向上冒泡;否则,停止;
	for i > 0 {
		parent := (i - 1) / 2
		if h.Elems[parent].value <= x .value{
			break
		}
		h.Elems[i] = h.Elems[parent]
		i = parent
	}
	h.Elems[i] = x
}

func (h *Heap) Pop() Node {
	if h.Size < 0 {
		var null Node
		return null
	}

	ret := h.Elems[0]
	// 将最后一个节点提到根节点,然后向下交换
	x := h.Elems[h.Size]
	i := 0
	for {
		l := 2*i + 1
		r := 2*i + 2

		if l >= h.Size {
			break
		}

		if r < h.Size && h.Elems[l].value > h.Elems[r].value  {
			l = r
		}

		if x.value <= h.Elems[l].value {
			break
		}

		h.Elems[i] = h.Elems[l]
		i = l
	}
	h.Size--
	h.Elems[i] = x
	return ret
}

func TripRainWater(martix [][]int,minheap *Heap){
	if len(martix)==0 || len(martix[0])==0 {
		return 
	}
	N:=len(martix)
	M:=len(martix[0])
	IsEnter:=[][]bool{}

	for i:=0;i<N;i++{
		tmp:=[]bool{}

		for i:=0;i<M;i++{

			tmp=append(tmp,false)
		}
		IsEnter=append(IsEnter,tmp)
	}
	fmt.Println(IsEnter)
	//把外围的数据加载到堆
	//先push行,并在isenter标记true
	for i:=0;i<M;i++{
		var node0 Node
		node0.value=martix[0][i]
		node0.row=0
		node0.col=i
		minheap.Push(node0)
		var nodeM Node
		nodeM.value=martix[N-1][i]
		nodeM.row=N-1
		nodeM.col=i
		minheap.Push(nodeM)
		IsEnter[0][i]=true
		IsEnter[N-1][i]=true
	}//push列,并在isenter标记true
	for i:=1;i<N-1;i++{
		var node1 Node
		node1.value=martix[i][0]
		node1.row=i
		node1.col=0
		minheap.Push(node1)
		var nodeN Node
		nodeN.value=martix[i][M-1]
		nodeN.row=i
		nodeN.col=M-1
		minheap.Push(nodeN)
		IsEnter[i][0]=true
		IsEnter[i][M-1]=true
	}
	for i:=0;i<N;i++{
		fmt.Println(IsEnter[i])
	}
	fmt.Println(minheap)


	max:=0
	water:=0
	for minheap.Size>=0{
		fmt.Println(minheap.Size)

		tmp:=minheap.Pop()
		fmt.Println(tmp)

		max=int(math.Max(float64(max),float64(tmp.value)))
		r:=tmp.row
		c:=tmp.col
		if r>0 && IsEnter[r-1][c]==false{
			var nodeup Node
			nodeup.value=martix[r-1][c]
			nodeup.row=r-1
			nodeup.col=c
			minheap.Push(nodeup)
			IsEnter[r-1][c]=true
			water+=int(math.Max(0,float64(max-nodeup.value)))
		}
		if r<N-1 && IsEnter[r+1][c]==false{
			var nodedown Node
			nodedown.value=martix[r+1][c]
			nodedown.row=r+1
			nodedown.col=c
			minheap.Push(nodedown)
			IsEnter[r+1][c]=true
			water+=int(math.Max(0,float64(max-nodedown.value)))
		}
		if c>0 && IsEnter[r][c-1]==false{
			var nodeleft Node
			nodeleft.value=martix[r][c-1]
			nodeleft.row=r
			nodeleft.col=c-1
			minheap.Push(nodeleft)
			IsEnter[r][c-1]=true
			water+=int(math.Max(0,float64(max-nodeleft.value)))
		}
		if c<M-1 && IsEnter[r][c+1]==false{
			var noderight Node
			noderight.value=martix[r][c+1]
			noderight.row=r
			noderight.col=c+1
			minheap.Push(noderight)
			IsEnter[r][c+1]=true
			water+=int(math.Max(0,float64(max-noderight.value)))
		}
	}
	fmt.Println(water)
}
func main(){
	var m [][]int
	t1:=[]int{8,8,8,8,8,8,8,8}
	t2:=[]int{8,9,1,2,1,4,5,8}
	t3:=[]int{8,7,1,1,3,2,6,8}
	t4:=[]int{8,6,1,2,5,7,2,8}
	t5:=[]int{8,1,3,5,1,2,1,8}
	t6:=[]int{8,7,9,2,1,4,6,8}
	t7:=[]int{8,8,8,8,5,8,8,8}
	m=append(m,t1)
	m=append(m,t2)
	m=append(m,t3)
	m=append(m,t4)
	m=append(m,t5)
	m=append(m,t6)
	m=append(m,t7)
	fmt.Println(m)
	N:=len(m)
	M:=len(m[0])
	minheap := NewHead(N*M)



	TripRainWater(m,minheap)



}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值