判断一个 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
示例 2:
输入: [ ["8","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"] ] 输出: false 解释: 除了第一行的第一个数字从 5 改为 8 以外,空格内其他数字均与 示例1 相同。 但由于位于左上角的 3x3 宫内有两个 8 存在, 因此这个数独是无效的。
说明:
- 一个有效的数独(部分已被填充)不一定是可解的。
- 只需要根据以上规则,验证已经填入的数字是否有效即可。
- 给定数独序列只包含数字
1-9
和字符'.'
。 - 给定数独永远是
9x9
形式的。
这个题看起来挺麻烦的。哈哈,这种比较是不是之前存在的题目我很容易想到了HashSet。
这个题数组打char比较难打所以先把char搞好:
char[,] board = new char[9, 9]
{
{ '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'},
//{'.', '.', '4', '.', '.', '.', '6', '3', '.'},
//{'.', '.', '.', '.', '.', '.', '.', '.', '.'},
//{'5', '.', '.', '.', '.', '.', '.', '9', '.'},
//{'.', '.', '.', '5', '6', '.', '.', '.', '.'},
//{'4', '.', '3', '.', '.', '.', '.', '.', '1'},
//{'.', '.', '.', '7', '.', '.', '.', '.', '.'},
//{'.', '.', '.', '5', '.', '.', '.', '.', '.'},
//{'.', '.', '.', '.', '.', '.', '.', '.', '.'},
//{'.', '.', '.', '.', '.', '.', '.', '.', '.'}
};
眼睛都看花了。。。
我用了俩个HashSet分别表示行排列,和竖排列,同时还有一组3个的HashSet是用作判断在3*3的宫中有没有重复的。核心就是俩个for循环按照顺序进行遍历。行排列和竖排列非常好进行判断,主要是3*3的宫判断,通过:
i%3==0
每三次i自增之后重置 HashSet<char>[] chars 。这样就能把每个数字放入自己的宫中,上码子:
public static bool Method1(char[,] board)
{
HashSet<char>[] chars = new HashSet<char>[3] {
new HashSet<char>() ,
new HashSet<char>() ,
new HashSet<char>()
};//声明3*3宫的数据组
HashSet<char> colChar = new HashSet<char>();//行排列
HashSet<char> rowChar = new HashSet<char>();//数排列
for (int i = 0; i < board.GetLength(0); i++)//行数i
{
#region 重置存储数据
colChar = new HashSet<char>();
rowChar = new HashSet<char>();
if (i % 3 == 0)//行数计数三个之后chars中三个都装满了3个宫,在开启新一组宫之前重置
{
chars = new HashSet<char>[3]{
new HashSet<char>() ,
new HashSet<char>() ,
new HashSet<char>()
};
}
#endregion
for (int j = 0; j < board.GetLength(1); j++)//列数j
{
#region 横向整行判断
if (!board[i, j].Equals('.') && !colChar.Add(board[i, j]))//表示横向添加的数字
{
return false;//返回表示不合适
}
#endregion
#region 纵向整列判断
if (!board[j, i].Equals('.') && !rowChar.Add(board[j, i])) //表示纵向添加的数字,这里i,j互相置位就可以实现
{
return false;//返回表示不合适
}
#endregion
#region 3*3数组判断
if (!chars[j / 3].Contains(board[i, j]))
{
if (!board[i, j].Equals('.'))
chars[j / 3].Add(board[i, j]);
}
else
return false; //返回表示不合适
#endregion
}
}
return true;
}
网上还有一种只用一个chars的HashSet,核心思路和这个一样就是转换查找的对应数值。