Want Help Cracking FAANG?

(Then click this)

×
Back to Question Bank

1197. Minimum Knight Moves - Leetcode Solution

Code Implementation

from collections import deque

class Solution:
    def minKnightMoves(self, x: int, y: int) -> int:
        # Use symmetry: only need to consider the first quadrant
        x, y = abs(x), abs(y)
        directions = [ (2,1), (1,2), (-1,2), (-2,1), (-2,-1), (-1,-2), (1,-2), (2,-1) ]
        visited = set()
        queue = deque()
        queue.append((0, 0, 0))  # (current_x, current_y, moves)
        visited.add((0, 0))
        while queue:
            cur_x, cur_y, moves = queue.popleft()
            if (cur_x, cur_y) == (x, y):
                return moves
            for dx, dy in directions:
                nx, ny = cur_x + dx, cur_y + dy
                if (nx, ny) not in visited and nx >= -2 and ny >= -2:
                    visited.add((nx, ny))
                    queue.append((nx, ny, moves + 1))
        return -1
      
#include <queue>
#include <set>
#include <utility>
#include <cstdlib>

class Solution {
public:
    int minKnightMoves(int x, int y) {
        x = abs(x); y = abs(y);
        int dirs[8][2] = { {2,1},{1,2},{-1,2},{-2,1},{-2,-1},{-1,-2},{1,-2},{2,-1} };
        std::queue<std::tuple<int,int,int>> q;
        std::set<std::pair<int,int>> visited;
        q.push({0, 0, 0});
        visited.insert({0, 0});
        while (!q.empty()) {
            auto [cx, cy, moves] = q.front(); q.pop();
            if (cx == x && cy == y) return moves;
            for (auto &dir : dirs) {
                int nx = cx + dir[0], ny = cy + dir[1];
                if (visited.count({nx, ny}) == 0 && nx >= -2 && ny >= -2) {
                    visited.insert({nx, ny});
                    q.push({nx, ny, moves + 1});
                }
            }
        }
        return -1;
    }
};
      
import java.util.*;

class Solution {
    public int minKnightMoves(int x, int y) {
        x = Math.abs(x); y = Math.abs(y);
        int[][] dirs = { {2,1},{1,2},{-1,2},{-2,1},{-2,-1},{-1,-2},{1,-2},{2,-1} };
        Queue<int[]> queue = new LinkedList<>();
        Set<String> visited = new HashSet<>();
        queue.offer(new int[]{0, 0, 0});
        visited.add("0,0");
        while (!queue.isEmpty()) {
            int[] curr = queue.poll();
            int cx = curr[0], cy = curr[1], moves = curr[2];
            if (cx == x && cy == y) return moves;
            for (int[] dir : dirs) {
                int nx = cx + dir[0], ny = cy + dir[1];
                String key = nx + "," + ny;
                if (!visited.contains(key) && nx >= -2 && ny >= -2) {
                    visited.add(key);
                    queue.offer(new int[]{nx, ny, moves + 1});
                }
            }
        }
        return -1;
    }
}
      
/**
 * @param {number} x
 * @param {number} y
 * @return {number}
 */
var minKnightMoves = function(x, y) {
    x = Math.abs(x); y = Math.abs(y);
    const dirs = [ [2,1],[1,2],[-1,2],[-2,1],[-2,-1],[-1,-2],[1,-2],[2,-1] ];
    const queue = [];
    const visited = new Set();
    queue.push([0, 0, 0]);
    visited.add('0,0');
    while (queue.length) {
        const [cx, cy, moves] = queue.shift();
        if (cx === x && cy === y) return moves;
        for (const [dx, dy] of dirs) {
            const nx = cx + dx, ny = cy + dy;
            const key = nx + ',' + ny;
            if (!visited.has(key) && nx >= -2 && ny >= -2) {
                visited.add(key);
                queue.push([nx, ny, moves + 1]);
            }
        }
    }
    return -1;
};
      

Problem Description

The Minimum Knight Moves problem asks: Given two integers x and y representing a target position on an infinite chessboard (with the knight starting at (0, 0)), what is the minimum number of moves required for the knight to reach (x, y)?

  • The chessboard is infinite in all directions.
  • The knight moves in the same way as in chess: in an "L" shape, i.e., two squares in one direction and one in a perpendicular direction, for a total of eight possible moves from any square.
  • Both x and y can be positive or negative integers.
  • You must return the minimum number of moves required to reach the target position.
  • There is always at least one valid solution.

Thought Process

The first instinct might be to try all possible moves from the starting position, recursively or iteratively, until the target is reached. However, since the board is infinite, a brute-force approach would be highly inefficient and could run forever if not managed carefully.

Instead, we need a way to systematically explore the possible positions, prioritizing those that are closer to the target. This is a classic scenario for Breadth-First Search (BFS), which explores all positions that can be reached in n moves before moving on to positions that require n+1 moves. BFS guarantees that the first time we reach the target, it will be via the shortest path.

Additionally, we can use symmetry: due to the knight's movement and the infinite board, reaching (x, y) is equivalent to reaching (|x|, |y|). This reduces the search space and avoids redundant calculations.

Solution Approach

  • Symmetry Optimization: Since the board is infinite and the knight's moves are symmetric, we can consider only the first quadrant by taking abs(x) and abs(y). This avoids redundant searches in other quadrants.
  • Breadth-First Search (BFS): We use a queue to store the current position and the number of moves taken to reach that position. BFS ensures that when we reach the target, it is via the shortest path.
  • Visited Set: To avoid revisiting positions and getting stuck in cycles, we keep a set of visited positions. This ensures each position is processed at most once.
  • Pruning the Search Space: Since the knight can move in all directions, but the shortest path will never go too far away from the target, we can safely restrict our search to positions where both coordinates are greater than or equal to -2. This is because the knight can sometimes overshoot and needs to backtrack a little, but never by much.
  • Moves Definition: The knight has 8 possible moves from any position, which we represent as pairs of coordinate changes.
  • Termination: When we dequeue a position that matches the target, we return the number of moves taken to reach it.

This approach is both efficient and guarantees correctness.

Example Walkthrough

Let's walk through an example where x = 2 and y = 1:

  1. Start at (0, 0) with 0 moves.
  2. Possible moves from (0, 0): (2, 1), (1, 2), (-1, 2), (-2, 1), (-2, -1), (-1, -2), (1, -2), (2, -1).
  3. We add all these positions to the queue with 1 move.
  4. Dequeue (2, 1): this matches our target! So, the answer is 1 move.

For a more complex example, like (5, 5), BFS would continue exploring all positions reachable in 1 move, then 2 moves, and so on, until it reaches (5, 5), always ensuring that the first time it does so is via the shortest path.

Time and Space Complexity

  • Brute-force: A naive recursive solution would have exponential time complexity, as it could revisit the same positions many times and explore an enormous number of possible paths.
  • Optimized BFS: With BFS and symmetry, the time complexity is roughly O(N^2) where N is the distance to the target, because in the worst case, we may visit all positions within a square of side O(N). However, pruning and symmetry reduce the actual number of positions visited.
  • Space Complexity: The space complexity is also O(N^2) due to the queue and the visited set storing all positions up to the target.
  • In practice, the BFS with symmetry and pruning is very fast for all reasonable input values.

Summary

The Minimum Knight Moves problem is elegantly solved using Breadth-First Search, leveraging symmetry to minimize unnecessary computation. By exploring all possible positions in increasing order of moves and pruning redundant states, we ensure both efficiency and correctness. The key insight is recognizing the infinite, symmetric nature of the chessboard and the knight's movement, allowing us to dramatically reduce the search space and guarantee the shortest path is found.