题目:判断一个 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
解析:题目我像已经够清楚了,一开始我的想法可能就是暴力破解,每一行每一列,再每一个单元格找,是否有相同的数,但直觉告诉我们肯定没那么复杂的,那样做相当于同样的数被你遍历了三次,从时间复杂度来说就不ok了。因此思考可不可以每个数只遍历一次就可以将这个数放在对应的那一行或那一列、那一个方格的存储集合中。具体看算法吧,个人觉得核心的主要是如何将那9方格中的数存放在对应的方格中。
class Solution {
public boolean isValidSudoku(char[][] board) {
//定义三个大小为9的数组,分别存放每一行,每一列,每个方格中的9个数。
//数组的类型是map,即每一个数都可以存放键值对
HashMap []rows = new HashMap[9];
HashMap []columns = new HashMap[9];
HashMap []boxes = new HashMap[9];
//之前只是定义了三个map的引用,还没有创建对象,因此下面的循环就是对数组的每一个值进行实例化,之后才能够对其进行.put()等操作
for (int i=0;i<9;i++){
rows[i] = new HashMap();
columns[i] = new HashMap();
boxes[i] = new HashMap();
}
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){//双重循环遍历每一个数
if(board[i][j] != '.'){//只存数字
int temp = (int)board[i][j];//这是将字符转化为整数
int boxIndex = i/3*3+j/3;//这便是处在方格中的每个数应该存放的位置的索引,读者可以根据上面的彩图进行逐一分析,对于方格0中的9个数用改boxIndex 得到的值都是0,因此这9个数都会被放在boexs[0]当中。
if(rows[i].containsKey(temp)||columns[j].containsKey(temp)||boxes[boxIndex].containsKey(temp)){
return false;//containsKey方法用来判断map中的key是否已经存在,先判断后存值
}
rows[i].put(temp,i);//使用put方法将当前这个数存放在键当中,其实val存放什么值都没有所谓,因为之前我们只用到了containsKey来判断key是否存在
columns[j].put(temp,j);//注意放置的位置是j,对应j列
boxes[boxIndex].put(temp,boxIndex);//注意放置的位置boxIndex
}
}
}
return true;
}
}
PS:若有解释不清或者又差错的地方,还望积极指正,欢迎留言!