解题思路

这是一个经典的回溯算法问题。需要通过尝试不同的数字来填充空格,直到找到一个合法的解。

关键点:

  1. 使用回溯算法尝试每个空格的可能数字
  2. 检查行、列、3x3小方格是否合法
  3. 优化搜索策略,提前剪枝
  4. 找到解后立即返回

算法步骤:

  1. 找到一个空格(值为0的位置)
  2. 尝试填入1-9的数字
  3. 检查是否合法
  4. 递归求解下一个空格
  5. 如果无法填入,回溯并尝试其他数字

代码

#include <bits/stdc++.h>
using namespace std;

class Solution {
private:
    bool is_valid(vector<vector<int>>& board, int row, int col, int num) {
        // 检查行
        for (int x = 0; x < 9; x++) {
            if (board[row][x] == num) return false;
        }
        
        // 检查列
        for (int x = 0; x < 9; x++) {
            if (board[x][col] == num) return false;
        }
        
        // 检查3x3方格
        int start_row = 3 * (row / 3);
        int start_col = 3 * (col / 3);
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                if (board[start_row + i][start_col + j] == num) {
                    return false;
                }
            }
        }
        
        return true;
    }
    
    bool solve_sudoku(vector<vector<int>>& board) {
        for (int row = 0; row < 9; row++) {
            for (int col = 0; col < 9; col++) {
                if (board[row][col] == 0) {
                    for (int num = 1; num <= 9; num++) {
                        if (is_valid(board, row, col, num)) {
                            board[row][col] = num;
                            if (solve_sudoku(board)) {
                                return true;
                            }
                            board[row][col] = 0;
                        }
                    }
                    return false;
                }
            }
        }
        return true;
    }
    
public:
    void solve(vector<vector<int>>& board) {
        solve_sudoku(board);
    }
};

int main() {
    vector<vector<int>> board(9, vector<int>(9));
    
    // 读取输入
    for (int i = 0; i < 9; i++) {
        for (int j = 0; j < 9; j++) {
            cin >> board[i][j];
        }
    }
    
    Solution solution;
    solution.solve(board);
    
    // 输出结果
    for (int i = 0; i < 9; i++) {
        for (int j = 0; j < 9; j++) {
            cout << board[i][j] << (j == 8 ? "\n" : " ");
        }
    }
    
    return 0;
}
import java.util.*;

public class Main {
    static class Solution {
        private int[][] board;
        
        // 检查在指定位置放置数字是否合法
        private boolean isValid(int row, int col, int num) {
            // 检查行
            for (int x = 0; x < 9; x++) {
                if (board[row][x] == num) {
                    return false;
                }
            }
            
            // 检查列
            for (int x = 0; x < 9; x++) {
                if (board[x][col] == num) {
                    return false;
                }
            }
            
            // 检查3x3方格
            int startRow = row - row % 3;
            int startCol = col - col % 3;
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 3; j++) {
                    if (board[i + startRow][j + startCol] == num) {
                        return false;
                    }
                }
            }
            
            return true;
        }
        
        // 使用回溯法解数独
        private boolean solveSudoku() {
            int row = -1;
            int col = -1;
            boolean isEmpty = false;
            
            // 找到一个空位置
            for (int i = 0; i < 9; i++) {
                for (int j = 0; j < 9; j++) {
                    if (board[i][j] == 0) {
                        row = i;
                        col = j;
                        isEmpty = true;
                        break;
                    }
                }
                if (isEmpty) {
                    break;
                }
            }
            
            // 如果没有空位置,说明解决完成
            if (!isEmpty) {
                return true;
            }
            
            // 尝试填入1-9
            for (int num = 1; num <= 9; num++) {
                if (isValid(row, col, num)) {
                    board[row][col] = num;
                    if (solveSudoku()) {
                        return true;
                    }
                    board[row][col] = 0;
                }
            }
            
            return false;
        }
        
        public void solve(int[][] sudokuBoard) {
            this.board = sudokuBoard;
            solveSudoku();
        }
    }
    
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int[][] board = new int[9][9];
        
        // 读取输入
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                board[i][j] = sc.nextInt();
            }
        }
        
        Solution solution = new Solution();
        solution.solve(board);
        
        // 输出结果
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                System.out.print(board[i][j]);
                if (j < 8) {
                    System.out.print(" ");
                }
            }
            System.out.println();
        }
        
        sc.close();
    }
}
class Solution:
    def solve(self, board: list) -> bool:
        def is_valid(row: int, col: int, num: int) -> bool:
            # 检查行
            for x in range(9):
                if board[row][x] == num:
                    return False
            
            # 检查列
            for x in range(9):
                if board[x][col] == num:
                    return False
            
            # 检查3x3方格
            start_row, start_col = 3 * (row // 3), 3 * (col // 3)
            for i in range(3):
                for j in range(3):
                    if board[start_row + i][start_col + j] == num:
                        return False
            
            return True
        
        def solve_sudoku() -> bool:
            # 找到一个空格
            for row in range(9):
                for col in range(9):
                    if board[row][col] == 0:
                        # 尝试填入1-9
                        for num in range(1, 10):
                            if is_valid(row, col, num):
                                board[row][col] = num
                                if solve_sudoku():
                                    return True
                                board[row][col] = 0
                        return False
            return True
        
        solve_sudoku()
        return board

# 读取输入
board = []
for _ in range(9):
    row = list(map(int, input().split()))
    board.append(row)

solution = Solution()
result = solution.solve(board)

# 输出结果
for row in result:
    print(' '.join(map(str, row)))

算法及复杂度

时间复杂度

  • 最坏情况:,需要尝试每个格子的所有可能
  • 实际情况:由于剪枝和约束传播,运行时间远小于理论上限

空间复杂度

  • 递归深度最大为81: =
  • 总空间复杂度:

优化策略

  1. 优先填充约束最多的格子
  2. 使用位运算优化状态检查
  3. 使用数组预存储每行、列、方格的可用数字
  4. 使用Dancing Links算法(精确覆盖问题)