[LeetCode 37] Sudoku Solver

题意

    解一个大小为 9*9 的数独。


思路

    回溯法。

    存储每一行、每一列、每个块分别有哪些数字已经使用过,每次填写新的数字之前都要检查,如果当前的数字是可行的,则递归地检查、填写下一个数字。递归函数的返回值可以用来判断是否有解,在第 i 行第 j 列时,如果已经找到了解,就直接返回,否则往当前位置填另外一个数字。

    递归的结束条件是:位置越界。这表明已经填完了整个数独。


python代码

class Solution:
    def __init__(self):
        self.rowvis = []
        self.colvis = []
        self.blockvis = []
        
        for i in range(0, 9):
            self.rowvis.append([False] * 9)
            self.colvis.append([False] * 9)
            self.blockvis.append([False] * 9)
        
    def solveSudoku(self, board):
        """
        :type board: List[List[str]]
        :rtype: void Do not return anything, modify board in-place instead.
        """
        
        sx = -1
        sy = -1
        for i in range(0, 9):
            for j in range(0, 9):
                if board[i][j] != '.':
                    num = int(board[i][j]) - 1
                    self.rowvis[i][num] = True
                    self.colvis[j][num] = True
                    self.blockvis[self.getBlock(i, j)][num] = True
                elif sx == -1:
                    sx = i
                    sy = j
        self.dfs(board, sx, sy)
    
    
    def getBlock(self, x, y):
        return (x // 3) * 3 + y // 3
    
    def dfs(self, board, x, y):
        if x == 9:
            return 1
        
        r = x
        c = y
        while True:
            c += 1
            if c == 9:
                r += 1
                c = 0
            if r == 9:
                break
            if board[r][c] == '.':
                break
        
        for i in range(0, 9):
            if self.rowvis[x][i] or self.colvis[y][i] or self.blockvis[self.getBlock(x, y)][i]:
                continue
            board[x][y] = str(i + 1)
            self.rowvis[x][i] = True
            self.colvis[y][i] = True
            self.blockvis[self.getBlock(x, y)][i] = True
            
            if self.dfs(board, r, c):
                return 1
            
            board[x][y] = '.'
            self.rowvis[x][i] = False
            self.colvis[y][i] = False
            self.blockvis[self.getBlock(x, y)][i] = False
            
        return 0


C++代码

class Solution
{
public:
    Solution() : n(9)
    {
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                rowvis[i][j]=colvis[i][j]=blockvis[i][j]=false;
    }
    void solveSudoku(vector<vector<char>>& board)
    {
        int sx=-1,sy=-1;
        for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
        {
            if(board[i][j]!='.')
            {
                board[i][j]-='1';
                int num=board[i][j];
                rowvis[i][num]=true;colvis[j][num]=true;
                blockvis[getBlock(i,j)][num]=true;
            }
            else if(sx==-1)
                sx=i,sy=j;
        }
        dfs(board,sx,sy);
        for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            board[i][j]+='1';
    }
    
private:
    int n;
    array<array<bool,9>,9> rowvis;
    array<array<bool,9>,9> colvis;
    array<array<bool,9>,9> blockvis;
    
    int getBlock(int x, int y) { return (x/3)*3+y/3; }
    int dfs(vector<vector<char>>& board, int x, int y)
    {
        if(x==n)
            return 1;
        int r=x,c=y;
        while(true)
        {
            c++;if(c>=n) r++,c=0;
            if(r>=n) break;
            if(board[r][c]=='.') break;
        }
        for(int i=0;i<n;i++)
        {
            if(rowvis[x][i] || colvis[y][i] || blockvis[getBlock(x,y)][i])
                continue;
            rowvis[x][i]=colvis[y][i]=blockvis[getBlock(x,y)][i]=true;
            board[x][y]=i;
            if(dfs(board,r,c))
                return 1;
            board[x][y]='.';
            rowvis[x][i]=colvis[y][i]=blockvis[getBlock(x,y)][i]=false;
        }
        
        return 0;
    }
};

猜你喜欢

转载自blog.csdn.net/PerfectCherryBlossom/article/details/80217707