2021.8.4 力扣-有效的数独

 

目录

题目链接:

题目描述:

方法一:

方法二:

方法三:


题目链接:

36. 有效的数独 - 力扣(LeetCode)

题目描述:

请你判断一个 9x9 的数独是否有效。只需要 根据以下规则 ,验证已经填入的数字是否有效即可。

1.数字 1-9 在每一行只能出现一次。
2.数字 1-9 在每一列只能出现一次。
3.数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)
数独部分空格内已填入了数字,空白格用 '.' 表示。

注意:

一个有效的数独(部分已被填充)不一定是可解的。
只需要根据以上规则,验证已经填入的数字是否有效即可。

方法一:

class Solution {
public:
    bool isValidSudoku(vector<vector<char>>& board) {
        unordered_map<int,int> maps;
        for(int i=0 ; i<9 ; i++)    //规则1
        {
            for(int j=0 ; j<9 ; j++)
            {
                if(board[i][j]!='.' && maps[board[i][j]]==0)
                {
                    maps[board[i][j]]++;
                }
                else if(board[i][j]!='.' && maps[board[i][j]]==1) 
                //说明这一行出现了重复数字
                {
                    return false;
                }
            }
            maps.clear();
        }
        for(int j=0 ; j<9 ; j++)    //规则2
        {
            for(int i=0 ; i<9 ; i++)
            {
                if(board[i][j]!='.' && maps[board[i][j]]==0)
                {
                    maps[board[i][j]]++;
                }
                else if(board[i][j]!='.' && maps[board[i][j]]==1) 
                //说明这一列出现了重复数字
                {
                    return false;
                }
            }
            maps.clear();
        }
        for(int x=3 ; x<=9 ; x+=3)   //规则3
        {
            for(int y=3 ; y<=9 ; y+=3)
            {
                for(int i=x-3 ; i<x ; i++)
                {
                    for(int j=y-3 ; j<y ; j++)
                    {
                        if(board[i][j]!='.' && maps[board[i][j]]==0)
                        {
                            maps[board[i][j]]++;
                        }
                        else if(board[i][j]!='.' && maps[board[i][j]]==1) 
                        //说明这一3×3宮内出现了重复数字
                        {
                            return false;
                        }
                    }
                }
                maps.clear();
            }
        }
        return true;
    }
};

思来想去,也想不到有什么快速方便的方法,还是用简单的for循环分别实现3条规则吧,再用哈希表来判断是否出现了重复的元素,在判断完一行/一列/一个3×3宫后,记得用clear()清除哈希表。

方法二:

class Solution {
public:
    bool isValidSudoku(vector<vector<char>>& board) {
        vector<vector<int>> row(9,vector<int>(9,0));  //存储每一行
        vector<vector<int>> col(9,vector<int>(9,0));  //存储每一列
        vector<vector<int>> box(9,vector<int>(9,0));  //存储每一个3×3宫
        //定义二维数组,每个二维数组初始化为9个元素都是vector<int>的一维数组,每个一维数组又初始化为9个元素都是0
        for(int i=0 ; i<9 ; i++)
        {
            for(int j=0 ; j<9 ; j++)
            {
                if(board[i][j]=='.')
                {
                    continue;
                }
                else
                {
                    int val = board[i][j]-'1';  
                    int boxindex = (i/3)*3 + j/3;   //宫的编号,即第几个宫
                    if(row[i][val]==0 && col[j][val]==0 && box[boxindex][val]==0)
                    {
                        row[i][val] = 1;
                        col[j][val] = 1;
                        box[boxindex][val] = 1;
                    }
                    else
                    {
                        return false;
                    }
                }
            }
        }
        return true;
    }
};

对比自己写的方法一,这种方法只需遍历一遍81个格子即可,虽然时间复杂度不变,但这种写法更简洁明了。自己在想题目的过程中,一直不知道怎么才能将前两条规则合并到一起,没想到可以直接将三条规则都整合到一起判断,只需使用三个二维数组,分别用来存储行、列和宫即可。

其中关于boxindex:

                                ​​​​​​​        ​​​​​​​       

 将表格划分成的9个宫都加上编号,那么(i/3)*3+j/3就能够计算出对应的编号,找到某一格子位于哪一个宫内。

这个方法二真的是很巧妙的方法!

方法三:

时隔一年多重新做,首先想到的是利用位运算来充当哈希表

class Solution {
public:
    //判断是否重复出现,如果重复出现返回true
    bool judge(int x, int y)
    {
        if (x & y) return true;
        return false;
    }
    bool isValidSudoku(vector<vector<char>>& board) {
        vector<int> a = {0, 0, 0, 1, 1, 1, 2, 2, 2};
        vector<int> row(9, 0), col(9, 0), box(9, 0);    //对应行,列,宫
        for (int i = 0; i < 9; i++)
        {
            for (int j = 0; j < 9; j++)
            {
                if (board[i][j] == '.') continue;
                int val = board[i][j] - '0';
                int count = a[i] * 3 + a[j];    //当前的val位于第count个宫里
                //如果有重复出现的数字,就返回false
                if (judge(row[i], (1 << val)) || judge(col[j], (1 << val)) || judge(box[count], (1 << val)))
                {
                    return false;
                }
                //更新
                row[i] |= (1 << val);
                col[j] |= (1 << val);
                box[count] |= (1 << val);
            }
        }
        return true;
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值