In an infinite chess board with coordinates from -infinity
to +infinity
, you have a knight at square [0, 0]
.
A knight has 8 possible moves it can make, as illustrated below. Each move is two squares in a cardinal direction, then one square in an orthogonal direction.
Return the minimum number of steps to move the knight to the square [x, y]
. It is guaranteed the answer exists.
Example 1:
Input: x = 2, y = 1 Output: 1 Explanation: [0, 0] -> [2, 1]
Example 2:
Input: x = 5, y = 5 Output: 4 Explanation: [0, 0] -> [2, 1] -> [4, 2] -> [3, 4] -> [5, 5]
Constraints:
-300 <= x, y <= 300
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
To find the fewest moves for a knight to reach a destination, the brute force method explores every possible path. It starts at the beginning and tries all possible knight moves, one by one, without any prior knowledge of the best route. This process continues until the target is reached.
Here's how the algorithm would work step-by-step:
def minimum_knight_moves_brute_force(target_x, target_y):
queue = [(0, 0, 0)] # Initial position and moves
visited = set()
visited.add((0, 0))
while queue:
current_x, current_y, moves = queue.pop(0)
if current_x == target_x and current_y == target_y:
return moves
knight_moves = [
(1, 2), (1, -2), (-1, 2), (-1, -2),
(2, 1), (2, -1), (-2, 1), (-2, -1)
]
for move_x, move_y in knight_moves:
next_x = current_x + move_x
next_y = current_y + move_y
# Avoid revisiting already explored positions
if (next_x, next_y) not in visited:
queue.append((next_x, next_y, moves + 1))
visited.add((next_x, next_y))
return -1 # If target is unreachable
This problem asks for the fewest moves a knight makes on a chessboard to reach a target square. We'll use a technique that explores outwards from the starting position, always checking the closest squares first, to find the target in the fewest steps.
Here's how the algorithm would work step-by-step:
from collections import deque
def minimum_knight_moves(start_row, start_column):
queue = deque([(0, 0, 0)])
visited = set([(0, 0)])
possible_moves = [(1, 2), (1, -2), (-1, 2), (-1, -2),
(2, 1), (2, -1), (-2, 1), (-2, -1)]
target_row = start_row
target_column = start_column
while queue:
current_row, current_column, moves = queue.popleft()
if current_row == target_row and current_column == target_column:
return moves
for move_row, move_column in possible_moves:
new_row = current_row + move_row
new_column = current_column + move_column
# Only explore valid and unvisited squares.
if (new_row, new_column) not in visited:
visited.add((new_row, new_column))
queue.append((new_row, new_column, moves + 1))
def minKnightMoves(target_row, target_column):
# Ensure target coordinates are positive.
target_row = abs(target_row)
target_column = abs(target_column)
# BFS to find the shortest path.
queue = deque([(0, 0, 0)])
visited = set([(0, 0)])
possible_moves = [(1, 2), (1, -2), (-1, 2), (-1, -2),
(2, 1), (2, -1), (-2, 1), (-2, -1)]
while queue:
current_row, current_column, moves = queue.popleft()
if current_row == target_row and current_column == target_column:
return moves
for move_row, move_column in possible_moves:
new_row = current_row + move_row
new_column = current_column + move_column
# Only explore valid and unvisited squares.
if new_row >= -1 and new_column >= -1 and (new_row, new_column) not in visited:
# Mark as visited to avoid re-exploration.
visited.add((new_row, new_column))
# Add to queue for further exploration.
queue.append((new_row, new_column, moves + 1))
Case | How to Handle |
---|---|
Target destination is the same as the starting position (0, 0). | Return 0 immediately since no moves are needed. |
Destination coordinates are extremely large, potentially leading to integer overflow or excessive computation. | Use a data structure like a hash set to prune the search space and explore only necessary coordinates within a reasonable boundary. |
Knight can only reach the target coordinate from one direction. | The BFS explores all possible paths, so this scenario is naturally covered and doesn't require special handling. |
Coordinates involve negative numbers. | Shift the coordinate system to the positive quadrant by adding an offset to both x and y coordinates. |
Very large target coordinates that might cause memory issues when storing visited coordinates. | Use a more memory-efficient data structure or a different search algorithm if memory becomes a constraint. |
The shortest path involves visiting the same coordinate multiple times. | The visited set correctly tracks the coordinates the algorithm has already visited to prevent infinite loops. |
The shortest path length exceeds a certain threshold, indicating an infinite or extremely long path. | Implement a maximum move limit to prevent the algorithm from running indefinitely. |
The target coordinate is on an 'edge' such that knight movements frequently take the knight out of bounds and then back. | Expand the boundaries of the visited set to consider coordinates slightly beyond the target coordinate and prevent out of bounds issues. |