数独有效性校验
判断一个 9x9 的数独是否有效。需要根据以下规则,验证已经填入的数字是否有效即可。
数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。
上图是一个部分填充的有效的数独。
以下输入是一个二维数组,部分元素已填入了数字,空白格用 ‘.’ 表示。
示例 1:
输入:
[
[“5”,”3”,”.”,”.”,”7”,”.”,”.”,”.”,”.”],
[“6”,”.”,”.”,”1”,”9”,”5”,”.”,”.”,”.”],
[“.”,”9”,”8”,”.”,”.”,”.”,”.”,”6”,”.”],
[“8”,”.”,”.”,”.”,”6”,”.”,”.”,”.”,”3”],
[“4”,”.”,”.”,”8”,”.”,”3”,”.”,”.”,”1”],
[“7”,”.”,”.”,”.”,”2”,”.”,”.”,”.”,”6”],
[“.”,”6”,”.”,”.”,”.”,”.”,”2”,”8”,”.”],
[“.”,”.”,”.”,”4”,”1”,”9”,”.”,”.”,”5”],
[“.”,”.”,”.”,”.”,”8”,”.”,”.”,”7”,”9”]
]
输出: true
粗暴的检测思路:
1. 用一个大小为 9 的辅助的bool数组,对以上3种情况进行校验,分别校验每一行的数字不重复,每一列的数字不重复,每个3 * 3 的矩阵内数字不重复
2. 遍历每个数字,判断该数字所在行 和 所在列 和所在的 3 * 3 矩阵是否存在相同数字,存在则无效。
以下使用解法1 实现,其实都差不多,解法2 由于没有辅助数组,时间复杂度会更大。
//将辅助数组重新初始化
void resetExternArr(bool *m)
{
for(int i=1; i< 10; i++)
m[i]=false;
}
bool isValidSudoku(char** board, int boardRowSize, int boardColSize)
{
bool m[10] = {0,0,0,0,0,0,0,0,0,0}; //辅助数组
//校验每一行的数是否重复
for (int i=0; i < boardRowSize; i++)
{
for (int j=0; j< boardColSize; j++)
{
if (board[i][j]=='.')
continue;
//如果遍历到的数字已经存在了,则直接返回无效
if (m[board[i][j]-'0'])
return false;
//将遍历过的数字对应的 bool 值置为 true
m[board[i][j]-'0'] = true;
}
//每遍历完一行,要将辅助数组重置。
resetExternArr(m);
}
//校验每一列的数是否重复,这里的循环与上面的循环都一样,只是访问的时候从 board[i][j] 变成了 board[j][i]
for (int i=0; i < boardRowSize; i++)
{
for (int j=0; j < boardColSize; j++)
{
if (board[j][i]=='.')
continue;
if (m[board[j][i]-'0'])
return false;
m[board[j][i]-'0'] = true;
}
resetExternArr(m);
}
//校验每一个3 * 3 的矩阵是否有重复元素
//最外层的两个 for 循环是对 3 * 3 的9个矩阵进行遍历
for (int start = 0; start <=6; start+=3)
{
for (int end = 0; end <=6; end+=3)
{
//内层的两个 for 循环是遍历该矩阵的 9 个元素
for (int i=start;i<start+3;i++)
{
for(int j=end; j<end+3;j++)
{
if (board[i][j]=='.')
continue;
if (m[board[i][j]-'0'])
return false;
m[board[i][j]-'0'] = true;
}
}
//判断完一个矩阵,将辅助数组重置
resetExternArr(m);
}
}
}