力扣37题(解数独、递归、回溯、未解)

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sudoku-solver
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

37.编写一个程序,通过填充空格来解决数独问题。
数独的解法需 遵循如下规则:
数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)
数独部分空格内已填入了数字,空白格用 ‘.’ 表示。

  1. 又是一道难题,只能通过题解来学习了。在解n皇后问题的时候,由于在每一行只能放置一个皇后,也就是说每次只需要在一行中的某一个位置进行修改值即可,所以只需要一个for循环就能解决每一行的放置问题;但是在解数独问题中,由于每一行的每个位置都需要填上数字,因此比n皇后问题更加复杂,需要用到两个for循环来解决问题,加上每个位置放置的数字有多种选择,所以实际上是三个for循环嵌套加上一个递归。与之前的回溯题目有点不太一样的是,之前的递归函数返回值一般都设置为void,这里递归函数的返回值设置为bool,因为题目说有唯一解,所以当找到一个符合要求的解时,就可以直接返回结束所有递归函数了。
  2. 具体看代码,代码还是相对比较清晰的,这些难题一般都是难在思路上,思路清晰了,代码看起来也不是很难。

//判断再board[row][col]位置上放val是否合适
bool isValid(int row, int col, char val, char** board, int boardSize) { 
    // 判断同行是否出现val
    for (int i = 0; i < boardSize; i++) {
        if (board[row][i] == val)
            return false;
    }

    // 判断同列是否出现val 
    for (int i = 0; i < boardSize; i++) {
        if (board[i][col] == val)
            return false;
    }

    // 判断val所在3*3宫内是否出现val
    int startRow = (row / 3) * 3;
    int startCol = (col / 3) * 3;
    for (int i = startRow; i < startRow + 3; i++) {
        for (int j = startCol; i < startCol + 3; j++) {
            if (board[i][j] == val)
                return false;
        }
    }
    return true;
}

bool backtracking(char** board, int boardSize) {
    for (int i = 0; i < boardSize; i++) { //遍历行
        for (int j = 0; j < boardSize; j++) { //遍历列
            if (board[i][j] != '.') //如果不是空白格则跳过
                continue;
            for (char k = '1'; k <= '9'; k++) { //每个空白格可以选择的数字有9个
                if (isValid(i, j, k, board, boardSize)) { //如果合法则再board[i][j]位置放置数字k
                    board[i][j] = k; 
                    if (backtracking(board, boardSize)) { //如果找到合适的解则立即返回
                        return true;
                    } 
                    board[i][j] = '.'; //回溯,撤销放置k
                }
            }
            return false; //一个位置9种数字都不行的话则无解
        }
    }
    return true; //能到这说明9*9宫格已经填满,即找到合适的解了
}

void solveSudoku(char** board, int boardSize, int* boardColSize){
    boardColSize = malloc(sizeof(int) * boardSize);
    for (int i = 0; i < boardSize; i++) {
        boardColSize[i] = boardSize;
    }
    backtracking(board, boardSize);
}
  1. 一生之敌AddressSanitizer,代码又报错了,真的是无语。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值