LeetCode-Sudoku Solver (递归解法)

题目地址: https://leetcode.com/problems/sudoku-solver/

// 将字符串的数独题转换成 int[9][9]

void setBoard(int board[9][9], char ** b, int boardRowSize, int boardColSize){

    for (int row = 0; row < boardRowSize; ++row)

    for (int col = 0; col < boardColSize; ++col){

        if (b[row][col] == '.')

            board[row][col] = 0;

        else

            board[row][col] = b[row][col] - '0';

    }

}

// 计算位置{row,col}的候选个数,并在cands返回候选列表

int calcCandNum(int board[9][9], int row, int col, int * cands){

    if (board[row][col] != 0)

        return 0;// 已知位置

    int cand[9] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 };//

    // 筛除 非法的数字

    // 按行筛除

    for (int i = 0; i < 9; ++i){

        if (board[row][i] != 0)

            cand[board[row][i] - 1] = 0;

    }

    

    // 按列

    for (int i = 0; i < 9; ++i){

        if (board[i][col] != 0)

            cand[board[i][col] - 1] = 0;

    }

    

    // 按block

    // 计算左上角坐标

    int r0, c0;

    r0 = (row / 3) * 3;

    c0 = (col / 3) * 3;

    for (int i = r0; i < r0 + 3; ++i)

    for (int j = c0; j < c0 + 3; ++j){

        if (board[i][j] != 0)

            cand[board[i][j] - 1] = 0;

    }

    // 剩下的1 的总和便是 候选个数

    int sum = 0;

    for (int i = 0; i < 9; ++i){

        if (cand[i]){

            cands[sum] = i + 1;

            sum++;

        }

    }

    return sum;

}



typedef struct tagCandidate{

    int row, col;           // 位置

    int n;                  // 候选个数

    int cands[9];           // 候选列表

    int solved;             // 数独是否已经解开

}Candidate;



// 从数独板中返回候选个数最少的位置,其候选信息存入 cand

void getCandidate(int board[9][9], Candidate* cand){

    int candList[9];

    int currN;

    cand->n = 10;

    cand->solved = 1;

    for (int row = 0; row < 9; ++row)

    for (int col = 0; col < 9; ++col){

        if (board[row][col] != 0){ // 该位置有值了

            continue;

        }

        // 说明数独还有空洞

        cand->solved = 0;



        // 计算该孔洞的候选个数,及候选序列

        currN = calcCandNum(board, row, col,candList);

        if (currN < cand->n){

            cand->n = currN;

            cand->row = row;

            cand->col = col;

            for (int i = 0; i < currN; ++i)

                cand->cands[i] = candList[i];

        }

    }    

}



int solveBoard(int board[9][9]){

    Candidate cand;

    getCandidate(board, &cand);

    if (cand.solved){

        return 1;

    }

    for (int i = 0; i < cand.n; ++i){

        // guess[cand.row][cand.col] = recursiveFlag;    // flag we guess 好像这个没什么用

        board[cand.row][cand.col] = cand.cands[i];    // fill what we guess

        if (solveBoard(board))

            // we'd solved it

            return 1;

        else{

            // we'd not solved it

            // clear what we guess

            // clearGuess(int board[9][9], int guess[])

            board[cand.row][cand.col] = 0;

        }

    }

    // 到这里来!! 不可能 , 无解????

    return 0;

}

// 将结果写回字符数组 b 中

void outputBoard(char **b, int board[9][9]){

    for(int row = 0; row < 9; ++row)

    for(int col = 0; col < 9; ++col){

        b[row][col] = '0' + (board[row][col]);

    }

}

void solveSudoku(char** b, int boardRowSize, int boardColSize) {

    int board[9][9];

    setBoard(board, b, boardRowSize, boardColSize);

    solveBoard(board);

    outputBoard(b,board);

}

 

你可能感兴趣的:(LeetCode)