LeetCode 5073. 進擊的騎士(Java)BFS


題目:5073. 進擊的騎士java

一個座標能夠從 -infinity 延伸到 +infinity 的 無限大的 棋盤上,你的 騎士 駐紮在座標爲 [0, 0] 的方格里。web

騎士的走法和中國象棋中的馬類似,走 「日」 字:即先向左(或右)走 1 格,再向上(或下)走 2 格;或先向左(或右)走 2 格,再向上(或下)走 1 格。算法

每次移動,他均可以按圖示八個方向之一前進。數組

馬

如今,騎士須要前去征服座標爲 [x, y] 的部落,請你爲他規劃路線。svg

最後返回所需的最小移動次數便可。本題確保答案是必定存在的。spa

示例 1:
輸入:x = 2, y = 1
輸出:1
解釋:[0, 0][2, 1]
示例 2:
輸入:x = 5, y = 5
輸出:4
解釋:[0, 0][2, 1][4, 2][3, 4][5, 5]
提示:
  • |x| + |y| <= 300
題解:

比較愚笨的辦法就是用 寬度優先搜索(BFS) 算法走到目標點爲止。我採用的也是這種算法。至於第一名的用的算法在下實在是看不懂,姑且先放着。我在CSDN論壇發的討論第一名寫的代碼的帖子.net

很明顯,棋盤是對稱的。直接將目標點座標取絕對值,調整到第一象限或 X 軸或 Y 軸。code

而後只在第一象限用BFS算得結果。xml

起點(0,0)是特殊點,直接返回 0。blog

點(1,1)也是特殊點,由於只在第一象限的話到達(1,1)至少要 4 步,可是若是能夠經過其餘象限的話,只須要 2 步便可到達(1,1)。

用二維數組 board[x + 3][y + 3] 表示到達點(r,c)的最少步數。

到達一個點後,若是合法,則步數等於上一個點的步數加 1。若是是目標點,直接返回步數,不然將座標入隊列。

時間複雜度: 在下無能爲力
空間複雜度: 在下仍是無能爲力

Java:
class Solution {
	public int minKnightMoves(	int x,
								int y) {
		x = Math.abs(x);// 調整到第一象限
		y = Math.abs(y);

		if (x + y == 0) {// 起點(0,0)
			return 0;
		}
		if (x == 1 && y == 1) {// 此算法是沒法計算點(1,1)的最少步數
			return 2;
		}

		int m = x + 3;
		int n = y + 3;
		int[][] board = new int[m][n];

		int[] dx = { 2, 1, -1, -2, -2, -1, 1, 2 };
		int[] dy = { 1, 2, 2, 1, -1, -2, -2, -1 };

		Queue<int[]> queue = new LinkedList<>();
		queue.add(new int[] { 0, 0 });

		while (!queue.isEmpty()) {
			int[] cur = queue.poll();// 出隊列
			for (int i = 0; i < 8; ++i) {
				int r = cur[0] + dx[i];
				int c = cur[1] + dy[i];
				if (r < 0 || r >= m || c < 0 || c >= n) {// 越界
					continue;
				}
				if (r + c == 0) {// 回到了起點
					continue;
				}
				if (board[r][c] == 0) {// 未訪問過當前點
					board[r][c] = board[cur[0]][cur[1]] + 1;
					if (r == x && c == y) {// 當前點就是目標點
						return board[r][c];// 返回結果
					}
					queue.add(new int[] { r, c });// 不是目標點,入隊列
				}
			}
		}
		return -1;
	}
}
相關文章
相關標籤/搜索