题目:给定一个n m的网格,其中每个单元格中可能有三种值。分别是0,1,2。
0表示这个格子为空,1表示这个格子有一个完好的苹果,2表示这个格子有一个腐烂的苹果。
腐烂的苹果每分钟会向上下左右四个方向的苹果传播一次病菌,并导致相邻的苹果腐烂。请问经过多少分钟,网格中不存在完好的苹果。如果有苹果永远不会腐烂则返回-1。
数据范围:1 n , m
100 , 网络中的值满足0
val
2
测试用例:
- 用例1
- 输入:[[2,1,1],[1,1,0],[0,1,1]]
- 输出:4
-
- 用例2
- 输入:[[2,1,1],[1,0,1],[1,1,1]]
- 输出:4
题目评价:
本人是最讨厌这种类型的题目,感觉特别麻烦(本人太菜了)。但这种题目的主流解法有两种:广度优先搜索(BFS)和 队列实现。
解题思路:
方法一(BFS):
首先分别将腐烂的橘子和新鲜的橘子保存在两个集合中;
模拟广度优先搜索的过程,方法是判断在每个腐烂橘子的四个方向上是否有新鲜橘子,如果有就腐烂它。每腐烂一次时间加 11,并剔除新鲜集合里腐烂的橘子;
当橘子全部腐烂时结束循环。
- func orangesRotting(grid [][]int) int {
- if !hasFresh(grid) {
- return 0
- }
-
- time := getTimes(grid)
-
- if hasFresh(grid) {
- return -1
- }
- return time
- }
-
- func hasFresh(grid [][]int) bool {
- for i := range grid {
- for _, val := range grid[i] {
- if 1 == val {
- return true
- }
- }
- }
- return false
- }
-
- func getTimes(grid [][]int) int {
- q := getQueue(grid)
- time := 0
-
- for len(q) > 0 {
- next := make([][]int, 0)
-
- for i := range q {
- row := q[i][0]
- col := q[i][1]
-
- next = setRot(grid, next, row-1, col)
- next = setRot(grid, next, row, col+1)
- next = setRot(grid, next, row+1, col)
- next = setRot(grid, next, row, col-1)
- }
-
- if len(next) != 0 {
- time++
- }
- q = next
- }
- return time
- }
-
- func getQueue(grid [][]int) [][]int {
- q := make([][]int, 0)
- for i := range grid {
- for j, val := range grid[i] {
- if 2 == val {
- q = append(q, []int{i, j})
- }
- }
- }
- return q
- }
-
- func setRot(grid, q [][]int, row, col int) [][]int {
- if row < 0 || col < 0 || row >= len(grid) || col >= len(grid[0]) || grid[row][col] != 1 {
- return q
- }
- grid[row][col] = 2
- q = append(q, []int{row, col})
- return q
- }
方法二( 队列实现):
- // 位置结构体
- type Pos struct {r,c int}
-
- // 队列
- type Queue []Pos
-
- // 入队
- func (this *Queue)Push(x Pos) {
- (*this) = append(*this,x)
- }
-
- // 出队
- func (this *Queue)Pop() Pos {
- res := (*this)[0]
- (*this) = (*this)[1:len(*this)]
- return res
- }
-
- // 判断队空
- func (this Queue)IsEmpty() bool {
- if len(this) == 0 {return true}
- return false
- }
-
- func orangesRotting(grid [][]int) int {
- res := -1
- n,m := len(grid),len(grid[0])
- dir := [][2]int{{1,0},{-1,0},{0,1},{0,-1}} // 方向矢量
- num1,num2 := 0,0 // 记录每一层腐烂橘子的数目
- flag := false // 记录初始状态下是否含有新鲜橘子
- var ql Queue
- for i := 0; i < n; i++ {
- for j := 0; j < m; j++ {
- if grid[i][j] == 2 { // 把第一层腐烂橘子入队并计数
- ql.Push(Pos{i,j})
- num1++
- }
- if grid[i][j] == 1 {flag = true}
- }
- }
- if num1 == 0 { // 若没有腐烂的橘子结果取决于有无新鲜的橘子
- if flag {return -1}
- return 0
- }
- for !ql.IsEmpty() {
- now := ql.Pop()
- for i := 0; i < 4; i++ {
- r,c := now.r+dir[i][0],now.c+dir[i][1]
- if r >= 0 && r < n && c >= 0 && c < m && grid[r][c] == 1 {
- grid[r][c] = 2
- ql.Push(Pos{r,c})
- num2++
- }
- }
- num1--
- if num1 == 0 { // 遍历完一层就记一次数
- res++
- num1 = num2
- num2 = 0
- }
- }
- // 判断是否还有新鲜的橘子
- for i := 0; i < n; i++ {
- for j := 0; j < m; j++ {
- if grid[i][j] == 1 {return -1}
- }
- }
- return res
- }
如果还是看不懂,可以看这个力扣网站上面的这道题目,相信对你有所帮助力扣https://leetcode.cn/problems/rotting-oranges/