力扣刷题【31-40】

36、 有效的数独

36.1 题目

36.2 分析

请添加图片描述

36.3 代码

class Solution {
public:
    bool isValidSudoku(vector<vector<char>>& board) {
        unordered_set<char> row={};
        unordered_set<char> cloumn;
        unordered_set<char> grid;

        for(int i=0;i<9;i++){
            for(int j=0;j<9;j++){
                if(board[i][j]!='.'&& !row.insert(board[i][j]).second){
                    
                      return false; 
                }
                if(board[j][i]!='.'&& !cloumn.insert(board[j][i]).second) return false;
                if(board[i%3*3+j/3][i/3*3+j%3]!='.'&& !grid.insert(board[i%3*3+j/3][i/3*3+j%3]).second)
                    return false;
            }
            row.clear();
            cloumn.clear();
            grid.clear();
        }
        return true;

    }
 
};

37、 解数独

37.1 题目

37.2 分析

请添加图片描述

37.3 代码

class Solution {
    private:
        int line[9];//记录当前行填入数字的情况
        int column[9];
        int block[3][3];//记录当前所在的3*3格子填入数字的情况
        vector<pair<int,int>> spaces;//未填数字的格子,spaces[0]代表第一个空格的所在行i所在列j
        bool valid;

public:
    void flip(int i,int j,int digit){
        line[i]^=1<<digit;
        column[j]^=1<<digit;
        block[i/3][j/3]^=1<<digit;

    }

    void dfs(vector<vector<char>>& board,int pos){
        if(pos==spaces.size()){
            valid=true;
            return;
        }
        auto[i,j]=spaces[pos];
        int mask=~(line[i] | column[j] |block[i/3][j/3])& 0x1ff;//获取所有可填入的数字,01101,代表该空格可填1,3,4
        for(;mask>0&&!valid;mask&=(mask-1)){//mask&=(mask-1)将最末位的1置0,即清除一个可填入的数字
            int lowmask=mask&(-mask);//获取最低位的可填入位置,即1010010则得到0000010
            int digit=__builtin_ctz(lowmask);//获取lowmask末尾有几个0
            board[i][j]='0'+digit+1;
            flip(i,j,digit);
            dfs(board,pos+1);//填入成功填下一个位置
            flip(i,j,digit);//不成功回溯,将之前填入位置置0

        }
    }
    void solveSudoku(vector<vector<char>>& board) {
        
        memset(line,0,sizeof(line));
        memset(column,0,sizeof(column));
        memset(block,0,sizeof(block));
        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;
                    flip(i,j,digit);//记录非空格的填入情况
                }
            }
        }

        dfs(board,0);

    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值