目录
题目链接:
题目描述:
请你判断一个 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;
}
};