💎题目描述
验证一个9x9的数独是否有效,遵循以下规则:
- 每行只能包含数字1-9,且每个数字只能出现一次。
- 每列只能包含数字1-9,且每个数字只能出现一次。
- 每个3x3的宫格(以粗实线分隔)只能包含数字1-9,且每个数字只能出现一次。 注意:
- 一个有效的数独不一定是可解的。
- 只需根据以上规则验证已填入的数字是否有效。
- 空白格用'.'表示。
❓解题思路
💥哈希表解法
🥇1.表格划分
我们将上述图片中的9x9棋盘格划分为9个分块box,分别命名为box[0]~box[8],然后在每一个小box里面再进行分块board,那么81个位置我们表示为下图所示的
🥈2.如何来区分这些块上的特定位置呢?
我们用board[i][j]来进行表示,我们先看数字i,将其分为三排,我们可以看出0、1、2再第一排;3、4、5在第二排;6、7、8在第三排;那么如何用i来表示这三排呢?
首先来看0、1、2
(0//3)*3=0
(1//3)*3=0
(2//3)*3=0
此时我们假设这一排给定的数字都在box[0]
首先来看3、4、5
(3//3)*3=3
(4//3)*3=3
(5//3)*3=3
此时我们假设这一排给定的数字都在box[3]
首先来看6、7、8
(6//3)*3=6
(7//3)*3=6
(8//3)*3=6
此时我们假设这一排给定的数字都在box[6]
然后我们再来看列,我们可以看出0、1、2再第一列;3、4、5在第二列;6、7、8在第三列;那么如何用j来表示这三列呢?
之前我们已经假设了在某个box了,那么第一列就是加0,第二列就是加1,第三列就是加2
来看0、1、2
0//3=0
1//3=0
2//3=0
来看3、4、5
3//3=1
4//3=1
5//3=1
来看6、7、8
6//3=2
7//3=2
8//3=2
也就是(i//3)*3+j//3
🥉3.代码
🏆python完整代码
class Solution:
def isValidSudoku(self, board):
# 初始化三个列表,分别用于记录每行、每列和每个3x3框中出现的数字
rows = [set() for _ in range(9)] # 每行
cols = [set() for _ in range(9)] # 每列
boxes = [set() for _ in range(9)] # 每个3x3框
# 遍历整个数独板
for i in range(9):
for j in range(9):
# 如果当前格子不为空
if board[i][j] != '.':
num = int(board[i][j]) # 将当前字符转换为数字
box_index = (i // 3) * 3 + j // 3 # 计算当前格子所属的3x3框的索引
# 检查当前数字是否已经出现在当前行、当前列或当前3x3框中
if num in rows[i] or num in cols[j] or num in boxes[box_index]:
return False # 如果出现重复,返回False
# 将当前数字加入到相应的行、列和框的集合中
rows[i].add(num)
cols[j].add(num)
boxes[box_index].add(num)
return True # 如果整个数独板满足条件,则返回True
# 测试用例
if __name__ == "__main__":
sol = Solution()
# 给定的数独板
board = [
["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"]
]
# 打印结果
print("是否是有效数独:", sol.isValidSudoku(board))
🏅c++完整代码
#include<iostream>
#include<vector>
#include<unordered_set>
using namespace std;
class Solution{
public:
bool isValidSudoku(vector<vector<char>>& board){
vector<unordered_set<char>> rows(9);// 用于记录每行中出现的数字的哈希表
vector<unordered_set<char>> cols(9);// 用于记录每列中出现的数字的哈希表
vector<unordered_set<char>> boxes(9); // 用于记录每个3x3框中出现的数字的哈希表
for(int i=0;i<9;i++){ //遍历行
for(int j=0;j<9;j++){ //遍历列
char num = board[i][j];//获取当前格子的数字
if(num != '.'){
int box_index = (i/3)*3 + j/3;// 计算当前格子所属的3x3框的索引
if(rows[i].count(num) || cols[j].count(num) || boxes[box_index].count(num)){
return false; // 如果当前数字已经在当前行、当前列或当前3x3框中出现过,则返回false
}
rows[i].insert(num); // 将当前数字加入到相应的行的哈希表中
cols[j].insert(num); // 将当前数字加入到相应的列的哈希表中
boxes[box_index].insert(num); // 将当前数字加入到相应的3x3框的哈希表中
}
}
}
return true;
}
};
int main(){
Solution sol;
vector<vector<char>> board = { // 给定的数独板
{'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'}
};
// 输出结果
cout << "Is valid sudoku: " << boolalpha << sol.isValidSudoku(board) << endl;
return 0;
}
🎖java完整代码
import java.util.HashSet;
class isValidSudoku {
public boolean isValidSudoku1(char[][] board) {
HashSet<Character>[] rows = new HashSet[9]; // 用于记录每行中出现的数字的哈希表
HashSet<Character>[] cols = new HashSet[9]; // 用于记录每列中出现的数字的哈希表
HashSet<Character>[] boxes = new HashSet[9]; // 用于记录每个3x3框中出现的数字的哈希表
// 初始化哈希表
for (int i = 0; i < 9; i++) {
rows[i] = new HashSet<Character>();
cols[i] = new HashSet<Character>();
boxes[i] = new HashSet<Character>();
}
// 遍历数独板
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
char num = board[i][j];
if (num != '.') { // 如果当前格子不为空
int box_index = (i / 3) * 3 + j / 3; // 计算当前格子所属的3x3框的索引
if (rows[i].contains(num) || cols[j].contains(num) || boxes[box_index].contains(num)) {
return false; // 如果当前数字已经在当前行、当前列或当前3x3框中出现过,则返回false
}
rows[i].add(num); // 将当前数字加入到相应的行的哈希表中
cols[j].add(num); // 将当前数字加入到相应的列的哈希表中
boxes[box_index].add(num); // 将当前数字加入到相应的3x3框的哈希表中
}
}
}
return true; // 如果整个数独板满足条件,则返回true
}
}
// 测试用例
class Main {
public static void main(String[] args) {
isValidSudoku sol = new isValidSudoku();
// 给定的数独板
char[][] board = {
{'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'}
};
// 输出结果
System.out.println("Is valid sudoku: " + sol.isValidSudoku1(board));
}
}