题目
给你一个 n x n 的二进制矩阵 grid 中,返回矩阵中最短 畅通路径 的长度。如果不存在这样的路径,返回 -1 。
二进制矩阵中的 畅通路径 是一条从 左上角 单元格(即,(0, 0))到 右下角 单元格(即,(n - 1, n - 1))的路径,该路径同时满足下述要求:
路径途经的所有单元格都的值都是 0 。
路径中所有相邻的单元格应当在 8 个方向之一 上连通(即,相邻两单元之间彼此不同且共享一条边或者一个角)。
畅通路径的长度 是该路径途经的单元格总数。
示例 1:
输入:grid = [[0,1],[1,0]] 输出:2
思路:
- 从 {0,0}出发【加入队列】,经过八个方向
- 每次到达一个点,只要满足条件,就加入队列,加入队列意味着下一轮会从该节点出发[也就是 A点出发到达B点,下次以B点为起点出发到达C点,每次到达一个点后,就以到达的点为起点]
- 已经被走过的点就不用再走了,应为那个点说明有人提前到过了
- 只有当前到达的点 是 右下角的点 就可以直接返回,不需要遍历剩余的
注: 因为是最短路径,需要明确并认同,最先到达右下角的一次走法,最短路径可以理解为,多个人A从点出发去B点,每个人的速度相同,那么最先到达B点肯定是找到最短路径的那个人边界。- 如果只有一个点,并且为0 ,那么直接返回 1 [也可以不提前判断,放到最后直接返回左下角点的值即可]
- 如果左上角或者右下角的点 是 1 那么说明没有路径直接返回 -1
- 由于需要的是 路径经过的格子数,因此只需要对 grid[0][0]提前赋值为 1,赋值为1能同时保证下一轮不会再回到起点
解决方法
func shortestPathBinaryMatrix(grid [][]int) int {
// 边界条件1 如果左上角第一个数为0,则没有解
if grid[0][0] == 1 {
return -1
}
// 边界条件2 如果矩阵长度是1且第一个数是1,则也没有解
if len(grid) == 1 && len(grid[0]) == 1 {
return 1
}
// 创建搜索方向
var direction = [][]int{
{-1, -1},
{-1, 0},
{-1, 1},
{0, 1},
{0, -1},
{1, -1},
{1, 0},
{1, 1},
}
// 创建访问列表,布尔矩阵
visited := make([][]bool, 0)
// 创建路径矩阵,整型矩阵
distance := make([][]int, 0)
// 创建矩阵
for i := 0; i < len(grid); i++ {
visited = append(visited, make([]bool, len(grid[0])))
distance = append(distance, make([]int, len(grid[0])))
}
// 初始化矩阵
visited[0][0], distance[0][0] = true, 1
// 创建列表,用于记录坐标值:(x)行的索引值*行数 + (y)列数
queue := []int{0}
// 当坐标数大于0时
for len(queue) > 0 {
// 更新列表
cur := queue[0]
queue = queue[1:]
// 解析切片中的横纵坐标
curx, cury := cur/len(grid[0]), cur%len(grid[0])
// 遍历8联通域每个方向上的值
for d := 0; d < 8; d++ {
nextx := curx + direction[d][0]
nexty := cury + direction[d][1]
// 坐标在表格内 && 该位置没有走过 && 该位置的值=0
if isInBoard(grid, nextx, nexty) && !visited[nextx][nexty] && grid[nextx][nexty] == 0 {
// 向切片中存入坐标值
queue = append(queue, nextx*len(grid[0])+nexty)
// 设置访问矩阵对应的坐标为true
visited[nextx][nexty] = true
// 更新距离矩阵中对应的值
distance[nextx][nexty] = distance[curx][cury] + 1
if nextx == len(grid)-1 && nexty == len(grid[0])-1 {
return distance[nextx][nexty]
}
}
}
}
// 坐标数等于0,说明没有,则返回-1
return -1
}
func isInBoard(board [][]int, x, y int) bool {
return x >= 0 && x < len(board) && y >= 0 && y < len(board[0])
}