(104)37. 解数独(leetcode)

题目链接:
https://leetcode-cn.com/problems/sudoku-solver/
难度:困难
37. 解数独
	编写一个程序,通过已填充的空格来解决数独问题。
	一个数独的解法需遵循如下规则:
	数字 1-9 在每一行只能出现一次。
	数字 1-9 在每一列只能出现一次。
	数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。
	空白格用 '.' 表示。
Note:
	给定的数独序列只包含数字 1-9 和字符 '.' 。
	你可以假设给定的数独只有唯一解。
	给定数独永远是 9x9 形式的。

这题有点难 对我来说。。。。 没做出来
看了下题解 勉强写了个递归(没有任何优化的 这应该是最差的做法了)

class Solution {
public:
    bool line[9][9];
    bool column[9][9];
    bool block[3][3][9];
    bool valid;
    vector<pair<int,int>> spaces;

    void dfs(vector<vector<char>>& board,int pos){
        if(spaces.size()==pos){
            valid=true;
            return;
        }
        auto [i, j] = spaces[pos];
        for(int digit=0;digit<9&&!valid;++digit){
            if(!line[i][digit]&&!column[j][digit]&&!block[i/3][j/3][digit]){
                line[i][digit]=true;
                column[j][digit]=true;
                block[i/3][j/3][digit]=true;
                board[i][j]=digit+'0'+1;
                dfs(board,pos+1);
                line[i][digit]=false;
                column[j][digit]=false;
                block[i/3][j/3][digit]=false;
            }
        }
    }

    void solveSudoku(vector<vector<char>>& board) {
        memset(line, false, sizeof(line));
        memset(column, false, sizeof(column));
        memset(block, false, sizeof(block));
        valid = false;
        for(int i=0;i<9;++i){
            for(int j=0;j<9;++j){
                if(board[i][j]=='.'){
                    spaces.emplace_back(i,j);
                }else{
                    int digit=board[i][j]-'0'-1;
                    line[i][digit]=true;
                    column[j][digit]=true;
                    block[i/3][j/3][digit]=true;
                }
            }
        }
        dfs(board,0);
    }
};

另一种方法 也是看的题解(非官方) 一位大佬的 做个标记大佬的解答 学到了 bitset (第一次接触)这种骚操作
按照大佬的思路来的 大佬np啊。。。 我感觉我下次碰到可能还不会。。。。。

class Solution {
public:
    vector<bitset<9>> rows;
    vector<bitset<9>> cols;
    vector<vector<bitset<9>>> cells;

    void solveSudoku(vector<vector<char>>& board){
        rows = vector<bitset<9>>(9, bitset<9>());
        cols = vector<bitset<9>>(9, bitset<9>());
        cells = vector<vector<bitset<9>>>(3, vector<bitset<9>>(3, bitset<9>()));

        int cnt = 0;
        // 初始化rows cols cells
        // cnt共有多少个空位
        for (int i=0; i<board.size();i++){
            for (int j=0; j<board[i].size();j++){
                cnt+=(board[i][j]=='.');
                if(board[i][j]=='.'){
                    continue;
                }
                int n=board[i][j]-'1';
                rows[i]|=(1 << n);
                cols[j]|=(1 << n);
                cells[i/3][j/3]|=(1<<n);
            }
        }
        dfs(board, cnt);
    }

    bool dfs(vector<vector<char>>& board, int cnt){
        if(cnt==0){
            return true;
        }
        auto next=getnext(board);
        // 找出可填的数字 位=1时 对应的
        auto bits=getPossibleStatus(next[0], next[1]);
        if(bits.count()==0){
            return false;
        }
        for(int i=0;i<bits.size();++i){
            if(!bits.test(i)){
                continue;
            }
            fillNum(next[0],next[1],i,true);
            board[next[0]][next[1]] = i+'1';
            if(dfs(board,cnt-1)){
                return true;
            }
            fillNum(next[0],next[1],i,false);
            board[next[0]][next[1]]='.';
        }
        return false;
    }
    // 找到限制条件最大的位置(可选数字最少)
    vector<int> getnext(vector<vector<char>>& board){
        vector<int> ret;
        int mincnt=10;
        for(int i=0;i<board.size();++i){
            for(int j=0;j<board[i].size();++j){
                if(board[i][j]!='.'){
                    continue;
                }
                auto cur=getPossibleStatus(i,j);
                if(cur.count()>mincnt){
                    continue;
                }
                ret={i,j};
                mincnt=cur.count();
            }
        }
        return ret;
    }
    // 主要是判断限制条件的多少  越多,可能放的数字的个数越少
    bitset<9> getPossibleStatus(int x,int y){
        return ~(rows[x]|cols[y]|cells[x/3][y/3]);
    }
    // 更新数组 
    void fillNum(int x,int y,int n,bool fillFlag){
        rows[x][n]=fillFlag?1:0;
        cols[y][n]=fillFlag?1:0;
        cells[x/3][y/3][n]=fillFlag?1:0;
    }

};

你可能感兴趣的:(leetcode)