You are given a chessboard of infinite size where the coordinates of each cell are defined by integer pairs (x, y). The knight piece moves in an L-shape, either two squares horizontally and one square vertically, or two squares vertically and one square horizontally.
Write a function to determine the minimum number of moves required for the knight to move from the starting position (0, 0) to the target position (x, y). Assume that it is always possible to reach the target position, and that x and y are both integers in the range [-200, 200]
Example 1
Input:
x = 1y = 2
Output: 1
Explanation: The knight can move from (0, 0) to (1, 2) in one move.
Example 2
x = 4y = 4
Output: 4
Explanation: The knight can move from (0, 0) to (4, 4) in four moves ( [0, 0] -> [2, 1] -> [4, 2] -> [6, 3] -> [4, 4] )
Explanation
We can model this problem as a graph where each cell on the chessboard is a node, and the neighbors of a cell are the cells that can be reached by a knight’s move from that cell. Since this is a shortest path problem, we can use a breadth-first search (BFS) traversal to find the minimum number of moves required to reach the target cell (x, y) starting from the cell (0, 0).
Step 1: Initialize the Queue and Visited Set
We start by initializing our BFS queue with the starting cell (0, 0) along with the number of moves required to reach that cell, which is 0 to start. We also initialize a set to keep track of the cells we have visited, so that we don’t revisit them (to avoid infinite loops).
Step 2: Perform BFS Traversal
We then perform a BFS traversal by repeatedly dequeuing from the front of the queue. Each time we dequeue, we get both the current knight position, and the number of moves required to reach that position. We then check if the current knight position is the target cell (x, y). If it is, we return the number of moves required to reach that cell.
Otherwise, for each valid knight move from the current position that has not been visited before, we add that position to the queue, along with the number of moves required to reach that position (which is 1 + the current # of moves). We also mark the current cell as visited.
Solution
from collections import dequeclass Solution: def minimum_knight_moves(self, x: int, y: int) -> int: directions = [(2, 1), (2, -1), (-2, 1), (-2, -1), (1, 2), (1, -2), (-1, 2), (-1, -2)] # Step 1: Initialize the queue and visited set queue = deque([(0, 0, 0)]) visited = set((0, 0)) # Step 2: Perform BFS traversal while queue: # (cx, cy) is the current knight position cx, cy, moves = queue.popleft() if (cx, cy) == (x, y): return moves # check all possible moves of the knight from the current position for dx, dy in directions: nx, ny = cx + dx, cy + dy # if the new position is not visited yet, add it to the queue # also mark it as visited and increment the number of moves if (nx, ny) not in visited: visited.add((nx, ny)) queue.append((nx, ny, moves + 1)) # if the target position is not reachable, return -1 return -1
class Solution { public int minimumKnightMoves(int x, int y) { int[][] directions = {{2, 1}, {2, -1}, {-2, 1}, {-2, -1}, {1, 2}, {1, -2}, {-1, 2}, {-1, -2}}; // Step 1: Initialize the queue and visited set Queue<int[]> queue = new LinkedList<>(); queue.offer(new int[]{0, 0, 0}); Set<String> visited = new HashSet<>(); visited.add("0,0"); // Step 2: Perform BFS traversal while (!queue.isEmpty()) { // [cx, cy] is the current knight position int[] current = queue.poll(); int cx = current[0], cy = current[1], moves = current[2]; if (cx == x && cy == y) { return moves; } // check all possible moves of the knight from the current position for (int[] dir : directions) { int nx = cx + dir[0]; int ny = cy + dir[1]; String key = nx + "," + ny; // if the new position is not visited yet, add it to the queue // also mark it as visited and increment the number of moves if (!visited.contains(key)) { visited.add(key); queue.offer(new int[]{nx, ny, moves + 1}); } } } // if the target position is not reachable, return -1 return -1; }}
type Position struct { X, Y, Moves int}func minimumKnightMoves(x int, y int) int { directions := [][2]int{{2, 1}, {2, -1}, {-2, 1}, {-2, -1}, {1, 2}, {1, -2}, {-1, 2}, {-1, -2}} // Step 1: Initialize the queue and visited set queue := []Position{{0, 0, 0}} visited := make(map[[2]int]bool) visited[[2]int{0, 0}] = true // Step 2: Perform BFS traversal for len(queue) > 0 { // current is the current knight position current := queue[0] queue = queue[1:] cx, cy, moves := current.X, current.Y, current.Moves if cx == x && cy == y { return moves } // check all possible moves of the knight from the current position for _, dir := range directions { nx := cx + dir[0] ny := cy + dir[1] pos := [2]int{nx, ny} // if the new position is not visited yet, add it to the queue // also mark it as visited and increment the number of moves if !visited[pos] { visited[pos] = true queue = append(queue, Position{nx, ny, moves + 1}) } } } // if the target position is not reachable, return -1 return -1}
class Solution { minimumKnightMoves(x: number, y: number): number { const directions: [number, number][] = [[2, 1], [2, -1], [-2, 1], [-2, -1], [1, 2], [1, -2], [-1, 2], [-1, -2]]; // Step 1: Initialize the queue and visited set const queue: [number, number, number][] = [[0, 0, 0]]; const visited = new Set<string>(); visited.add("0,0"); // Step 2: Perform BFS traversal while (queue.length > 0) { // [cx, cy] is the current knight position const [cx, cy, moves] = queue.shift()!; if (cx === x && cy === y) { return moves; } // check all possible moves of the knight from the current position for (const [dx, dy] of directions) { const nx = cx + dx; const ny = cy + dy; const key = `${nx},${ny}`; // if the new position is not visited yet, add it to the queue // also mark it as visited and increment the number of moves if (!visited.has(key)) { visited.add(key); queue.push([nx, ny, moves + 1]); } } } // if the target position is not reachable, return -1 return -1; }}