【LeetCode/LintCode】 題解丨網易面試題:騎士的最短路線
阿新 • • 發佈:2020-09-14
給定騎士在棋盤上的 初始 位置(一個2進位制矩陣 0 表示空 1 表示有障礙物),找到到達 終點 的最短路線,返回路線的長度。如果騎士不能到達則返回 -1 。
- 起點跟終點必定為空.
- 騎士不能碰到障礙物.
- 路徑長度指騎士走的步數.
線上評測地址:
說明
如果騎士的位置為(x,y),他下一步可以到達以下這些位置:
(x + 1, y + 2) (x + 1, y - 2) (x - 1, y + 2) (x - 1, y - 2) (x + 2, y + 1) (x + 2, y - 1) (x - 2, y + 1) (x - 2, y - 1)
樣例
例1:
輸入:
[[0,0,0],
[0,0,0],
[0,0,0]]
source = [2, 0] destination = [2, 2]
輸出: 2
解釋:
[2,0]->[0,1]->[2,2]
例2:
輸入:
[[0,1,0],
[0,0,1],
[0,0,0]]
source = [2, 0] destination = [2, 2]
輸出:-1
演算法:BFS
樸素BFS搜搜最短路,BFS概括來說就是像雷達一樣,一層一層進行尋找目標點。當找到目標點後進行回溯。從而找到最佳路徑。也就是說每走一步都要找到到達該點的最短的路徑,最終得到到達所有點的最短路徑,這題每一次的下一步做了規定,按照日字形跳到下一步。
- 根據下一跳位置建立方向陣列
- dx=[1, 1, 2, 2, -1, -1, -2, -2]
- dy=[2, -2, 1, -1, 2, -2, 1, -1]
- 遍歷八個方向,進行搜尋
- 用grid陣列標註是否訪問過某點
- 注意判斷下一跳的位置是否越界
複雜度分析
- 時間複雜度O(n*m)
- 最多跑一邊圖 n為圖的行數,m為圖的列數,最多跑一邊圖,即n*m
- 空間複雜度O(n*m)
- 所有點的資訊 n為圖的行數,m為圖的列數
public class Solution { /** * @param grid: a chessboard included 0 (false) and 1 (true) * @param source: a point * @param destination: a point * @return: the shortest path */ public int shortestPath(boolean[][] grid, Point source, Point destination) { int n = grid.length,m = grid[0].length; if (n == 0 || m == 0) { return -1; } int[] dx = {1, 1, 2, 2, -1, -1, -2, -2}; int[] dy = {2, -2, 1, -1, 2, -2, 1, -1}; Queue<Point> queue = new LinkedList<>(); queue.offer(source); grid[source.x][source.y] = true; int ans = 0; while (!queue.isEmpty()) { int size = queue.size(); for (int k = 0; k < size; k++) { Point cur = queue.poll(); //到達終點,返回距離 if (cur.x == destination.x && cur.y == destination.y) { return ans; } for (int i = 0; i < 8; i++) { Point next = new Point ( cur.x + dx[i], cur.y + dy[i] ); //判斷下一條可否到達 if (is_in_bound(next,n,m) && grid[next.x][next.y] == false) { queue.offer(next); grid[next.x][next.y] = true; } } } ans++; } return -1; } //判斷是否越界 private boolean is_in_bound(Point next,int n,int m) { return 0 <= next.x && next.x < n && 0 <= next.y && next.y < m; } }
更多題解參考:九章演算法官網