# 06. Knight's Tour Problem

The problem can be found at the following link: 🔗 [Question Link](https://www.geeksforgeeks.org/problems/the-knights-tour-problem/1)

## **🧩 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

```cpp
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

```cpp
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**

1. **Initialize Board:**
   * Create an `n × n` board initialized with `-1` (unvisited cells).
   * Mark the starting position `(0, 0)` with `0` (first step).
2. **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[]` and `dy[]`.
3. **Recursive Exploration:**
   * From current position `(x, y)` at step `s`, 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`.
4. **Base Case:**
   * If `s == n * n`, all cells are visited - return `true`.
5. **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.
6. **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++)**

```cpp
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>>();
    }
};
```

<details>

<summary>⚡ View Alternative Approaches with Code and Analysis</summary>

### 📊 **2️⃣ Warnsdorff's Heuristic Approach**

#### 💡 Algorithm Steps:

1. Always move the knight to the square with minimum accessibility (fewest onward moves).
2. Count unvisited neighbors for each possible next position.
3. Choose the position with the least number of unvisited neighbors.
4. Significantly reduces backtracking by making smarter choices.

```cpp
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};
        auto deg = [&](int x, int y) {
            int c = 0;
            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) c++;
            }
            return c;
        };
        function<bool(int, int, int)> solve = [&](int x, int y, int s) {
            b[x][y] = s;
            if (s == n * n - 1) return true;
            int minDeg = 9, minIdx = -1;
            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) {
                    int d = deg(nx, ny);
                    if (d < minDeg) minDeg = d, minIdx = i;
                }
            }
            if (minIdx != -1) {
                if (solve(x + dx[minIdx], y + dy[minIdx], s + 1)) return true;
            }
            b[x][y] = -1;
            return false;
        };
        return solve(0, 0, 0) ? b : vector<vector<int>>();
    }
};
```

#### 📝 **Complexity Analysis:**

* **Time:** ⏱️ O(n²) - Near-linear with heuristic guidance
* **Auxiliary Space:** 💾 O(n²) - Board storage and recursion stack

#### ✅ **Why This Approach?**

* Dramatically faster than pure backtracking
* Intelligently reduces search space
* Industry-standard heuristic for knight's tour

### 📊 **3️⃣ Iterative DFS with Stack**

#### 💡 Algorithm Steps:

1. Use an explicit stack to avoid recursion overhead.
2. Push starting position with step count onto stack.
3. Pop states and try all valid knight moves iteratively.
4. Backtrack by popping states when no valid moves exist.

```cpp
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};
        stack<tuple<int, int, int, int>> st;
        b[0][0] = 0;
        st.push({0, 0, 1, 0});
        while (!st.empty()) {
            auto [x, y, s, dir] = st.top();
            st.pop();
            if (s == n * n) return b;
            bool found = false;
            for (int i = dir; 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;
                    st.push({x, y, s, i + 1});
                    st.push({nx, ny, s + 1, 0});
                    found = true;
                    break;
                }
            }
            if (!found && s > 1) b[x][y] = -1;
        }
        return {};
    }
};
```

#### 📝 **Complexity Analysis:**

* **Time:** ⏱️ O(8^(n²)) - Explores all possible paths
* **Auxiliary Space:** 💾 O(n²) - Stack space proportional to board size

#### ✅ **Why This Approach?**

* Avoids recursion stack overflow for very large boards
* More control over backtracking process
* Suitable for systems with limited stack size

### 📊 **4️⃣ Divide and Conquer Approach**

#### 💡 Algorithm Steps:

1. Solve for smaller sub-boards and combine solutions.
2. Use precomputed patterns for standard board sizes.
3. Handle edge cases separately for odd-sized boards.
4. Merge partial tours to create complete solution.

```cpp
class Solution {
public:
    vector<vector<int>> knightTour(int n) {
        if (n < 5) {
            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>>();
        }
        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>>();
    }
};
```

#### 📝 **Complexity Analysis:**

* **Time:** ⏱️ O(8^(n²)) - Similar to basic backtracking
* **Auxiliary Space:** 💾 O(n²) - Board and recursion stack

#### ✅ **Why This Approach?**

* Can leverage precomputed patterns for efficiency
* Better for specific board sizes with known solutions
* Theoretical improvement for very large boards

### 🆚 **🔍 Comparison of Approaches**

| 🚀 **Approach**               | ⏱️ **Time Complexity** | 💾 **Space Complexity** | ✅ **Pros**                | ⚠️ **Cons**                |
| ----------------------------- | ---------------------- | ----------------------- | ------------------------- | -------------------------- |
| 🔄 **Simple Backtracking**    | 🔴 O(8^(n²))           | 🟢 O(n²)                | 📖 Easy to understand     | 🐌 Very slow for n>6       |
| 🔍 **Warnsdorff's Heuristic** | 🟢 O(n²)               | 🟢 O(n²)                | 🚀 Very fast practically  | ⚠️ May fail on some boards |
| 📊 **Iterative DFS**          | 🟡 O(8^(n²))           | 🟢 O(n²)                | 🎯 No stack overflow      | 🔧 More complex code       |
| 🔄 **Divide and Conquer**     | 🟡 O(8^(n²))           | 🟢 O(n²)                | ⭐ Good for specific sizes | 🔧 Complex implementation  |

#### 🏆 **Best Choice Recommendation**

| 🎯 **Scenario**                | 🎖️ **Recommended Approach**  | 🔥 **Performance Rating** |
| ------------------------------ | ----------------------------- | ------------------------- |
| 🏅 **Large boards (n ≥ 8)**    | 🥇 **Warnsdorff's Heuristic** | ★★★★★                     |
| 📖 **Small boards (n ≤ 6)**    | 🥈 **Simple Backtracking**    | ★★★☆☆                     |
| 🔧 **Deep recursion concerns** | 🥉 **Iterative DFS**          | ★★★★☆                     |
| 🎯 **Interview/Competitive**   | 🏅 **Basic Backtracking**     | ★★★★☆                     |

</details>

## **☕ Code (Java)**

```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)**

```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?](https://www.linkedin.com/in/patel-hetkumar-sandipbhai-8b110525a/). Let's make this learning journey more collaborative!

⭐ **If you find this helpful, please give this repository a star!** ⭐

***

#### 📍Visitor Count

<div align="center"><img src="https://visitor-badge.laobi.icu/badge?page_id=Hunterdii.GeeksforGeeks-POTD" alt="Visitor counter"></div>
