06. Knight's Tour Problem
β GFG solution to the Knight's Tour Problem: find a sequence where a knight visits every square on an nΓn chessboard exactly once using backtracking. π
The problem can be found at the following link: π Question Link
π§© Problem Description
You are given an integer n
, representing an n Γ n
chessboard with a Knight starting at the top-left corner (0, 0)
. Your task is to determine a valid Knight's Tour, where the Knight visits every square exactly once, following the standard movement rules of a chess Knight.
A Knight moves in an L-shape: two steps in one direction (horizontal or vertical) and one step perpendicular to that direction. For example, if a Knight is at cell (2, 2)
, it can move to any of these cells: (4, 3)
, (4, 1)
, (0, 3)
, (0, 1)
, (3, 4)
, (3, 0)
, (1, 4)
, and (1, 0)
.
Return the order in which each cell is visited (starting from 0). If a solution exists, return the sequence of numbers representing the order of visited squares. If no solution is possible, return an empty list.
π Examples
Example 1
Input: n = 5
Output: true
Explanation: A possible Knight's Tour in a 5x5 chessboard is:
[[0, 11, 2, 17, 20],
[3, 16, 19, 12, 7],
[10, 1, 6, 21, 18],
[15, 4, 23, 8, 13],
[24, 9, 14, 5, 22]]
Each number represents the step at which the Knight visits that cell, starting from (0, 0) as step 0.
Example 2
Input: n = 4
Output: false
Explanation: For n = 4, it is not possible to find a valid Knight's Tour, so return an empty list [].
π Constraints
$1 \le n \le 6$
β
My Approach
The optimal approach uses Backtracking with Depth-First Search (DFS) to explore all possible knight moves and find a valid tour:
Backtracking with DFS
Initialize Board:
Create an
n Γ n
board initialized with-1
(unvisited cells).Mark the starting position
(0, 0)
with0
(first step).
Define Knight Moves:
A knight can move in 8 possible directions:
(2,1)
,(1,2)
,(-1,2)
,(-2,1)
,(-2,-1)
,(-1,-2)
,(1,-2)
,(2,-1)
.Store these as direction arrays
dx[]
anddy[]
.
Recursive Exploration:
From current position
(x, y)
at steps
, try all 8 possible knight moves.For each valid move to
(nx, ny)
:Check if the new position is within bounds and unvisited.
Mark the cell with the current step number.
Recursively explore from the new position with step
s + 1
.
Base Case:
If
s == n * n
, all cells are visited - returntrue
.
Backtrack:
If a path doesn't lead to a solution, reset the cell to
-1
and try the next move.If no valid move exists from current position, backtrack to previous state.
Return Result:
If a complete tour is found, return the board with the visiting sequence.
Otherwise, return an empty list.
π Time and Auxiliary Space Complexity
Expected Time Complexity: O(8^(nΒ²)), where n is the size of the chessboard. In the worst case, we explore all possible knight move sequences. However, with pruning through backtracking, practical runtime is much better, especially for smaller boards (n β€ 6). The branching factor is 8 (possible knight moves) and maximum depth is nΒ².
Expected Auxiliary Space Complexity: O(nΒ²), where n is the size of the board. This includes space for the board storage and the recursion call stack which can go up to depth nΒ² in the worst case.
π§βπ» Code (C++)
class Solution {
public:
vector<vector<int>> knightTour(int n) {
vector<vector<int>> b(n, vector<int>(n, -1));
int dx[] = {2, 1, -1, -2, -2, -1, 1, 2}, dy[] = {1, 2, 2, 1, -1, -2, -2, -1};
function<bool(int, int, int)> solve = [&](int x, int y, int s) {
if (s == n * n) return true;
for (int i = 0; i < 8; i++) {
int nx = x + dx[i], ny = y + dy[i];
if (nx >= 0 && ny >= 0 && nx < n && ny < n && b[nx][ny] == -1) {
b[nx][ny] = s;
if (solve(nx, ny, s + 1)) return true;
b[nx][ny] = -1;
}
}
return false;
};
b[0][0] = 0;
return solve(0, 0, 1) ? b : vector<vector<int>>();
}
};
β Code (Java)
class Solution {
public ArrayList<ArrayList<Integer>> knightTour(int n) {
int[][] b = new int[n][n];
for (int[] r : b) Arrays.fill(r, -1);
int[] dx = {2, 1, -1, -2, -2, -1, 1, 2}, dy = {1, 2, 2, 1, -1, -2, -2, -1};
b[0][0] = 0;
if (solve(0, 0, 1, n, b, dx, dy)) {
ArrayList<ArrayList<Integer>> res = new ArrayList<>();
for (int[] r : b) {
ArrayList<Integer> row = new ArrayList<>();
for (int v : r) row.add(v);
res.add(row);
}
return res;
}
return new ArrayList<>();
}
boolean solve(int x, int y, int s, int n, int[][] b, int[] dx, int[] dy) {
if (s == n * n) return true;
for (int i = 0; i < 8; i++) {
int nx = x + dx[i], ny = y + dy[i];
if (nx >= 0 && ny >= 0 && nx < n && ny < n && b[nx][ny] == -1) {
b[nx][ny] = s;
if (solve(nx, ny, s + 1, n, b, dx, dy)) return true;
b[nx][ny] = -1;
}
}
return false;
}
}
π Code (Python)
class Solution:
def knightTour(self, n):
b = [[-1] * n for _ in range(n)]
dx, dy = [2, 1, -1, -2, -2, -1, 1, 2], [1, 2, 2, 1, -1, -2, -2, -1]
def solve(x, y, s):
if s == n * n: return True
for i in range(8):
nx, ny = x + dx[i], y + dy[i]
if 0 <= nx < n and 0 <= ny < n and b[nx][ny] == -1:
b[nx][ny] = s
if solve(nx, ny, s + 1): return True
b[nx][ny] = -1
return False
b[0][0] = 0
return b if solve(0, 0, 1) else []
π§ Contribution and Support
For discussions, questions, or doubts related to this solution, feel free to connect on LinkedIn: π¬ Any Questions?. Let's make this learning journey more collaborative!
β If you find this helpful, please give this repository a star! β
πVisitor Count
Last updated