package day06;
//判断一个9*9的熟读是否有效只需要根据以下规则,验证已经填入的数字是否有效即可。
//
// 数字 1-9 在每一行只能出现一次。
// 数字 1-9 在每一列只能出现一次。
// 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
public class IsValidSudoku {
public static void main(String[] args) {
//测试
char[][] board = {
{'.','.','.', '.','5','.', '.','1','.'},
{'.','4','.', '3','.','.', '.','.','.'},
{'.','.','.', '.','.','3', '.','.','1'},
{'8','.','.', '.','.','.', '.','2','.'},
{'.','.','2', '.','7','.', '.','.','.'},
{'.','1','5', '.','.','.', '.','.','.'},
{'.','.','.', '.','.','2', '.','.','.'},
{'.','2','.', '9','.','.', '.','.','.'},
{'.','.','4', '.','.','.', '.','.','.'},
};
//测试思路1
//boolean res = isValidSudoku(board);
//测试思路2
boolean res = isValidSudoku02(board);
System.out.println(res);
}
//思路:遍历该 9 x 9 数独 三 次,以确保:
//行中没有重复的数字。
//列中没有重复的数字。
//3 x 3 子数独内没有重复的数字。
public static boolean isValidSudoku(char[][] board) {
//判断行和列
if( !judgeRowAndCol(board,0,0,board.length, board.length) ) {
return false;
} else if (!judgeThree(board)) {
return false;
}
return true;
}
public static boolean judgeRowAndCol(char[][] board, int beginRow, int beginCol, int width, int height) {
HashSet<Character> setRow = new HashSet<>(9);
HashSet<Character> setCol = new HashSet<>(9);
for(int i = beginRow; i < width; i ++) {
setRow.clear();
setCol.clear();
for(int j = beginCol; j < width; j ++) {
//判断行
if(board[i][j] != '.') {
if(setRow.isEmpty()) {
setRow.add(board[i][j]);
} else if (setRow.contains(board[i][j])) {
return false;
} else {
setRow.add(board[i][j]);
}
}
//判断列
if(board[j][i] != '.') {
if(setCol.isEmpty()) {
setCol.add(board[j][i]);
} else if (setCol.contains(board[j][i])) {
return false;
} else {
setCol.add(board[j][i]);
}
}
}
}
return true;
}
//判断3*3宫格
public static boolean judgeThree(char[][] board) {
HashSet<Character> set = new HashSet<>(9);
for(int i = 0; i < board.length; i += 3) {
for(int j = 0; j < board.length; j += 3) {
set.clear();
//判断3*3宫格内的每一行,判断三行是否有重复的数字
for(int m = i; m < i + 3; m ++) {
for(int n = j; n < j + 3; n ++) {
if(board[m][n] != '.') {
if(set.isEmpty()) {
set.add(board[m][n]);
} else if (set.contains(board[m][n])) {
return false;
} else {
set.add(board[m][n]);
}
}
}
}
}
}
return true;
}
//思路2:根据上面的思路,我们可以在一次遍历中得到结果
public static boolean isValidSudoku02(char[][] board) {
//使用Map记录出现的数字及出现的次数
/*HashMap<Integer, Integer> [] rows = new HashMap[9];
HashMap<Integer, Integer> [] columns = new HashMap[9];
HashMap<Integer, Integer> [] boxes = new HashMap[9];
for (int i = 0; i < 9; i++) {
rows[i] = new HashMap<Integer, Integer>();
columns[i] = new HashMap<Integer, Integer>();
boxes[i] = new HashMap<Integer, Integer>();
}*/
//使用List
ArrayList<Integer>[] row = new ArrayList[9];
ArrayList<Integer>[] col = new ArrayList[9];
ArrayList<Integer>[] box = new ArrayList[9];
for(int i = 0; i < 9; i ++) {
row[i] = new ArrayList<>(9);
col[i] = new ArrayList<>(9);
box[i] = new ArrayList<>(9);
}
//根据所在的行i 和 所在的列j 计算出所在的子宫格= (i / 3) * 3 + j / 3
for(int i = 0; i < board.length; i ++) {
for(int j = 0; j < board.length; j ++) {
char num = board[i][j];
if(num != '.') {
int n = (int)num;
int box_index = (i / 3) * 3 + j / 3;
if(row[i].contains(n) || col[j].contains(n) || box[box_index].contains(n)) {
return false;
} else {
row[i].add(n);
col[j].add(n);
box[box_index].add(n);
}
}
}
}
return true;
}
}
判断一个9*9的数独是否有效的两个思路及JAVA代码
最新推荐文章于 2023-01-05 15:24:35 发布