LeetCode 37. 解数独

难度:困难。
标签:回溯法。

具体判断条件与上一题的相同,可见【36. 有效的数独

开始写的一直有问题,原因:

  • 在每次回溯结束时,没有将数据重置,即缺失 30-35行的代码。
  • solve没有返回bool值,由此没有办法完成剪枝的操作。
  • 4-11行的代码有问题,开始是这样写的:
	if(board[i][j] != '.'){
           if(j < 8){
               solve(board, i, j + 1, flags);
           }
           else if(i < 8){
               solve(board, i + 1, 0, flags);
           }
           else{
               return true; 
           }
       }

根本原因是对回溯法还不够熟悉,思路有点问题。

正确解法:

class Solution {
    bool solve(vector<vector<char>>& board, int i, int j, int flags[][10]){
        while(board[i][j] != '.'){
            if(j < 9)j++;
            else if(i < 8){
                i++;
                j = 0;
            }
            else return true;
        }
        
        int k1 = i , k2 = 9 + j, k3 = 18 + (i / 3) * 3 + (j / 3);
        for(int num = 1; num < 10; num++){
            if(flags[k1][num] == 0 && flags[k2][num] == 0 && flags[k3][num] == 0){
                board[i][j] = '0' + num;
                flags[k1][num] = 1;
                flags[k2][num] = 1;
                flags[k3][num] = 1;
                int new_i = i, new_j = j;
                if(j < 8) new_j = j + 1;
                else if(i < 8){
                    new_i = i + 1;
                    new_j = 0;
                }
                else return true;

                if(solve(board, new_i, new_j, flags)){
                    return true;
                }else{
                    board[i][j] = '.';
                    flags[k1][num] = 0;
                    flags[k2][num] = 0;
                    flags[k3][num] = 0;
                }
            }
        }
        return false;
    }

public:
    void solveSudoku(vector<vector<char>>& board) {
        int flags[27][10] = {0};
        for(int i = 0; i < 9; i++){
            for(int j = 0; j < 9; j++){
                if(board[i][j] == '.')continue;
                int num = board[i][j] - '0';
                int k1 = i , k2 = 9 + j, k3 = 18 + (i / 3) * 3 + (j / 3);
                flags[k1][num] = 1;
                flags[k2][num] = 1;
                flags[k3][num] = 1;
            }
        }
        solve(board, 0, 0, flags);
    }
};

结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值