####题目描述:
判断一个 9x9 的数独是否有效。只需要根据以下规则,验证已经填入的数字
是否有效即可。
1.数字 1-9 在每一行只能出现一次。
2.数字 1-9 在每一列只能出现一次。
3.数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。
要弄清楚这个问题,就是要知道验证的算法是什么.
也就是说我们,要在两次循环(一次外循环,一次内循环)中进行这三次验证.
前提(如何去验证是否存在重复的数字?)
验证的方法就是使用数组,你想一下,总共9个数字,你在验证这个数字在行里面是否
已经出现了,你构建一个数组,长度为10,专门用来验证行的,假设验证的当前数字是5,
那么你就在这个数组里面索引为5的位置设置为1(代表出现过了),如果在验证当前行
时,别的列还出现了5,那么你判断这个数组索引为4的位置是否为1,如果是1,代表重复,
直接返回
还有一个需要强调的问题,就是如果只是使用两次循环的话,本来就只能够验证81个
数,只能验证9行中每一行是否有重复的数据.
但是现在要做的同时要验证3处,行是否重复,列是否重复,宫是否重复.
每一次验证,能得到的是坐标(i跟j),
只有一个坐标(i,j)要验证三处:
问题的解决:
for(int i = 0; i < 9; i++) {
int[] row = new int[9];
for(int j = 0; j < 9; j++) {
if(board[i][j] != '.') { // 当前的坐标是验证行的
if(row[board[i][j] - '1'] == 1) {
return false;
} else {
row[board[i][j] - '1'] = 1;
}
}
}
循环到了(i,j)坐标,先获取这个值board[i][j],看一下这个值是否为'.',
先假设为6,开始时row这个数组的9个位置全是0,所以就会走
row[board[i][j] - '1'] = 1;
这段代码,然后数组的就变成了
[0, 0, 0, 0, 0, 1, 0, 0, 0] --- 这个数组此时的意义就是,当前行
存在6,因为索引为5的位置是1,代表6数字曾经在这一行出现过了.
注意这个数组是定义在这个内循环之外,外循环值内的,也就是说,当i为2时,换了一
行之后,就需要重新初始化.
需要注意的一点:
当在遍历第一行的数据是,(i,j)i的坐标全为0,说明是同一行,如果把i跟j的位置变换一下
变成(j,i),那么i都是0,也就是说,变成了一列了,列的数字都是0,
for(int i = 0; i < 9; i++){
int[] col = new int[9];
for(int j = 0; j < 9; j++) {
// 验证当前坐标的反置位置的元素是否在它的这一列存曾经出现过
if(board[j][i] != '.') { // 左边变成(j,i),就是验证列了
// 因为在这一次循环中,i都是不变的,变得都是j
if(col[board[j][i] - '1'] == 1) {
return false;
} else {
col[board[j][i] - '1'] = 1;
}
}
}
// 在这个外循环里面,每一次变得都是j,
}
假设i = 2,说明遍历到了这个二维数组的第三行了,当吧左边反过来,也就是说这
一次遍历第2行元素时,列都是2,就变成了,这些元素都是第三列元素了,所以就可以
进行列上面的判断是否出现重复了.
现在需要分析的问题是:
现在假设遍历到了第三行数据,当你遍历第三行第一个数是,你需要将这个左边(2,0)
坐标转换,转换成,遍历当前行,的当前列的元素时,需要查询到这个坐标的数字,所在的宫的所有的元素.
看这个坐标转换的算法:
@Test
public void test01() {
for(int i = 0; i < 9; i++) {
for(int j = 0; j < 9; j++) {
int cubeX = 3 * (i/3) + j/3;
int cubeY = 3 * (i%3) + j%3;
System.out.println("cubeX: " + cubeX + "- cubeY:" + cubeY);
}
System.out.println("----------------");
}
}
打印的结果:
cubeX: 0- cubeY:0
cubeX: 0- cubeY:1
cubeX: 0- cubeY:2
cubeX: 1- cubeY:0
cubeX: 1- cubeY:1
cubeX: 1- cubeY:2
cubeX: 2- cubeY:0
cubeX: 2- cubeY:1
cubeX: 2- cubeY:2
----------------
cubeX: 0- cubeY:3
cubeX: 0- cubeY:4
cubeX: 0- cubeY:5
cubeX: 1- cubeY:3
cubeX: 1- cubeY:4
cubeX: 1- cubeY:5
cubeX: 2- cubeY:3
cubeX: 2- cubeY:4
cubeX: 2- cubeY:5
----------------
cubeX: 0- cubeY:6
cubeX: 0- cubeY:7
cubeX: 0- cubeY:8
cubeX: 1- cubeY:6
cubeX: 1- cubeY:7
cubeX: 1- cubeY:8
cubeX: 2- cubeY:6
cubeX: 2- cubeY:7
cubeX: 2- cubeY:8
----------------
cubeX: 3- cubeY:0
cubeX: 3- cubeY:1
cubeX: 3- cubeY:2
cubeX: 4- cubeY:0
cubeX: 4- cubeY:1
cubeX: 4- cubeY:2
cubeX: 5- cubeY:0
cubeX: 5- cubeY:1
cubeX: 5- cubeY:2
----------------
cubeX: 3- cubeY:3
cubeX: 3- cubeY:4
cubeX: 3- cubeY:5
cubeX: 4- cubeY:3
cubeX: 4- cubeY:4
cubeX: 4- cubeY:5
cubeX: 5- cubeY:3
cubeX: 5- cubeY:4
cubeX: 5- cubeY:5
----------------
cubeX: 3- cubeY:6
cubeX: 3- cubeY:7
cubeX: 3- cubeY:8
cubeX: 4- cubeY:6
cubeX: 4- cubeY:7
cubeX: 4- cubeY:8
cubeX: 5- cubeY:6
cubeX: 5- cubeY:7
cubeX: 5- cubeY:8
----------------
cubeX: 6- cubeY:0
cubeX: 6- cubeY:1
cubeX: 6- cubeY:2
cubeX: 7- cubeY:0
cubeX: 7- cubeY:1
cubeX: 7- cubeY:2
cubeX: 8- cubeY:0
cubeX: 8- cubeY:1
cubeX: 8- cubeY:2
----------------
cubeX: 6- cubeY:3
cubeX: 6- cubeY:4
cubeX: 6- cubeY:5
cubeX: 7- cubeY:3
cubeX: 7- cubeY:4
cubeX: 7- cubeY:5
cubeX: 8- cubeY:3
cubeX: 8- cubeY:4
cubeX: 8- cubeY:5
----------------
cubeX: 6- cubeY:6
cubeX: 6- cubeY:7
cubeX: 6- cubeY:8
cubeX: 7- cubeY:6
cubeX: 7- cubeY:7
cubeX: 7- cubeY:8
cubeX: 8- cubeY:6
cubeX: 8- cubeY:7
cubeX: 8- cubeY:8
----------------
分析:
当循环走到i=2时,遍历到的是第三行的数据
当 i = 2 , j = 0时 cubeX: 0- cubeY:6
这个坐标是第三宫(宫二)的第一个元素(0,6)
当 i = 2 , j = 1时 cubeX: 0- cubeY:7
这个坐标是第三宫(宫二)的第二个元素(0,7)
当 i = 2, j = 2时 cubeX: 0- cubeY:8
这个坐标是第三宫(宫二)的第三个元素(0,8)
当 i = 2 , j = 3时 cubeX: 1- cubeY:6
这个坐标是第三宫(宫二)的第四个元素(1,6)
当 i = 2 , j = 4时 cubeX: 1- cubeY:7
这个坐标是第三宫(宫二)的第五个元素(1,7)
当 i = 2, j = 5时 cubeX: 1- cubeY:8
这个坐标是第三宫(宫二)的第六个元素(1,8)
当 i = 2 , j = 6时 cubeX: 2- cubeY:6
这个坐标是第三宫(宫二)的第七个元素(2,6)
当 i = 2 , j = 7时 cubeX: 2- cubeY:7
这个坐标是第三宫(宫二)的第八个元素(2,7)
当 i = 2, j = 8时 cubeX: 2- cubeY:8
这个坐标是第三宫(宫二)的第九个元素(2,8)
也就睡说当外循环走到i = 2 时间,课可以对宫二的元素进行判断是否存在重复事务元素
关键是将坐标(i,j)变成宫i的所有的坐标
*所以验证宫的做法就是:*
for(int i = 0; i < 9; i++){
int[] cube = new int[9];
for(int j = 0; j < 9; j++) {
int cubeX = 3 * (i/3) + j/3;
int cubeY = 3 * (i%3) + i%3;
if(board[cubeX][cubeY] != '.') {
if(cube[board[cubeX][cubeY] - 1] == '1') {
return false;
} else {
cube[board[cubeX][cubeY] - '1'] = 1;
}
}
}
}
###全部代码:
package solution_36;
import java.util.Arrays;
import org.junit.Test;
public class Solution {
public static boolean isValidSudoku(char[][] board) {
for(int i = 0; i < 9; i++) {
int[] row = new int[9];
int[] col = new int[9];
int[] cube = new int[9];
for(int j = 0; j < 9; j++) {
System.out.println("board[i][j] : [ i=" + i + "j = " + j + "] -- 值: " + board[i][j]);
if(board[i][j]!='.') {
if(row[board[i][j] - '1'] == 1) {
/*System.out.println("====");
System.out.println(row[board[i][j]]);
System.out.println("====");*/
return false;
} else {
row[board[i][j] - '1'] = 1;
System.out.println("row[] " + Arrays.toString(row) + " ---- board[i][j] = " + board[i][j]);
}
}
if(board[j][i] != '.') {
if(col[board[j][i] - '1'] == 1) {
return false;
} else {
col[board[j][i] - '1'] = 1;
System.out.println("col[] " + Arrays.toString(col) + "---- board[j][i] = " + board[j][i] );
}
}
// 每一宫内行列的变化
int cubeX = 3 * (i/3) + j/3;
int cubeY = 3 * (i%3) + j%3;
if(board[cubeX][cubeY] != '.') {
if(cube[board[cubeX][cubeY] - '1'] == 1) {
return false;
} else {
System.out.println("cubeX= " + cubeX + " cubeY=" + cubeY);
cube[board[cubeX][cubeY] - '1'] = 1;
System.out.println("cube[] " + Arrays.toString(cube) + " --- board[cubeX][cubeY] = " + board[cubeX][cubeY]);
}
}
}
System.out.println("row[] " + Arrays.toString(row));
System.out.println("col[] " + Arrays.toString(col));
System.out.println("cube[] " + Arrays.toString(cube));
}
return true;
}
public static void main(String[] args) {
// char[][] board = [['8','3','.','.','7','.','.','.','.']];
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(isValidSudoku(board));
}
@Test
public void test01() {
for(int i = 0; i < 9; i++) {
for(int j = 0; j < 9; j++) {
int cubeX = 3 * (i/3) + j/3;
int cubeY = 3 * (i%3) + j%3;
System.out.println("cubeX: " + cubeX + "- cubeY:" + cubeY);
}
System.out.println("----------------");
}
}
@Test
public void test02() {
int[] a = new int[9];
System.out.println(a.length);
}
}