Leetcode-36. 有效的数独
判断一个 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 形式的。
解法:遍历整个正方形,只要一直行中没有重复的,列中没有重复的,小正方形中没有重复的即可,时间复杂度,空间复杂度都是O(1)
- Java
使用HashSet,缺点慢,读取hashset时间慢于数组
class Solution {
public boolean isValidSudoku(char[][] board) {
for(int i = 0; i<9; i++){
HashSet<Character> rows = new HashSet<Character>();
HashSet<Character> columns = new HashSet<Character>();
HashSet<Character> cube = new HashSet<Character>();
for (int j = 0; j < 9;j++){
if(board[i][j]!='.' && !rows.add(board[i][j]))
return false;
if(board[j][i]!='.' && !columns.add(board[j][i]))
return false;
int RowIndex = 3*(i/3);
int ColIndex = 3*(i%3);
if(board[RowIndex + j/3][ColIndex + j%3]!='.' && !cube.add(board[RowIndex + j/3][ColIndex + j%3]))
return false;
}
}
return true;
}
}
使用数组,速度会快上很多
class Solution {
public boolean isValidSudoku(char[][] board) {
for (int i=0;i<9;i++) {
int[] cols = new int[9];
int[] rows = new int[9];
int[] blocks = new int[9];
for (int j=0;j<9;j++) {
// 遍历行,-‘1’是为了用0-8索引存下1-9
if (board[i][j] == '.') {}
else if (rows[board[i][j]-'1']==1) return false;
else rows[board[i][j]-'1']=1;
// 遍历列
if (board[j][i] == '.') {}
else if (cols[board[j][i]-'1']==1) return false;
else cols[board[j][i]-'1']=1;
// 遍历块,将ij坐标系转换到正方形坐标系,理解不了可以背
int m = i/3*3 + j/3;
int n = i%3*3 + j%3;
if (board[m][n]== '.') {}
else if (blocks[board[m][n]-'1']==1) return false;
else blocks[board[m][n]-'1']=1;
}
}
return true;
}
}
- Python
class Solution:
def isValidSudoku(self, board: List[List[str]]) -> bool:
for i in range(9):
rows = [0]*9
cols = [0]*9
blocks = [0]*9
for j in range(9):
if board[i][j]=='.':pass
elif rows[int(board[i][j])-1]==1: return False
else: rows[int(board[i][j])-1]=1
if board[j][i]=='.':pass
elif cols[int(board[j][i])-1]==1: return False
else: cols[int(board[j][i])-1]=1
m, n = i//3*3 + j//3, i%3*3 + j%3
if board[m][n]=='.':pass
elif blocks[int(board[m][n])-1]==1: return False
else : blocks[int(board[m][n])-1]=1
return True
Leetcode-37. 解数独
编写一个程序,通过已填充的空格来解决数独问题。
一个数独的解法需遵循如下规则:
- 数字 1-9 在每一行只能出现一次。
- 数字 1-9 在每一列只能出现一次。
- 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。
空白格用 ‘.’ 表示。
一个数独。
答案被标成红色。
Note:
给定的数独序列只包含数字 1-9 和字符 ‘.’ 。
你可以假设给定的数独只有唯一解。
给定数独永远是 9x9 形式的。
解法:使用dfs,每个格子查看能填的数,如果能填,填进去在将填完的board重新调用,如果有格子1-9都不能填了,return false,如果遍历到最后,所有格子都填完了,return true。时间复杂度,空间复杂度都是O(1)
- Java
class Solution {
public void solveSudoku(char[][] board) {
if (board==null || board.length==0) return ;
this.dfs(board);
}
public boolean dfs(char[][] board) {
for (int i=0;i<board.length;i++){
for (int j=0;j<board[0].length;j++) {
if (board[i][j]=='.') {
for (char c='1';c<='9';c++) { // must be <=9, cant be <10,cause 10 is no more character
if (this.isValid(board, i, j, c)) {
board[i][j] = c;
boolean res= this.dfs(board);
if (res==true) return true;
else board[i][j]='.';
}
}
return false;
}
}
}
return true;
}
public boolean isValid(char[][] board, int row, int col, char c) {
for (int i=0;i<9;i++) {
if (board[row][i]!='.' && board[row][i]==c) return false;
if (board[i][col]!='.' && board[i][col]==c) return false;
int m = row/3*3 + i/3;
int n = col/3*3 + i%3;
if (board[m][n]!='.' && board[m][n]==c) return false;
}
return true;
}
}
- Python
class Solution:
def solveSudoku(self, board: List[List[str]]) -> None:
if not board: return
self.board = board
self.dfs()
def dfs(self):
for i in range(len(self.board)):
for j in range(len(self.board[0])):
if self.board[i][j]=='.':
for c in range(1,10):
c = str(c)
if self.isValid(i,j,c):
self.board[i][j] = c
res = self.dfs()
if res: return True
else: self.board[i][j] = '.'
return False
return True
def isValid(self,row,col,c):
for i in range(9):
if (self.board[row][i]==c): return False
if (self.board[i][col]==c): return False
m = row//3*3 + i//3
n = col//3*3 + i%3
if (self.board[m][n]==c): return False
return True