题目:
矩阵的值代表这一点的高度,不同的高度会形成湖,求给定的一个矩阵能接多少的雨水
分析:
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)
}