一、题目描述

二、题目思路
- 对于行、列、块,分别预设九个哈希表,键值对<出现的数字,数字出现的总次数>,遍历所有行列,对每一行(列、块同理),键的个数如果小于值的总和,代表同一个数字出现了不止一次,则判定为false。
三、提交代码
import java.util.Collection;
class Solution {
public boolean isValidSudoku(char[][] board) {
for(int i=0;i<9;i++){
HashMap<Integer,Integer> maprow = new HashMap<>();
HashMap<Integer,Integer> mapcolumn = new HashMap<>();
HashMap<Integer,Integer> mapblock = new HashMap<>();
for(int j =0;j<9;j++){
int rowCurrent = (int)board[i][j] -(int)'0';
int columnCurrent = (int)board[j][i] -(int)'0';
int blockCurrent = (int)board[3*(i/3)+j/3][3*(i%3)+j%3] -(int)'0';
if(rowCurrent>0){
maprow.put(rowCurrent,maprow.getOrDefault(rowCurrent,0)+1);
}
if(columnCurrent>0){
mapcolumn.put(columnCurrent,mapcolumn.getOrDefault(columnCurrent,0)+1);
}
if(blockCurrent>0){
mapblock.put(blockCurrent,mapblock.getOrDefault(blockCurrent,0)+1);
}
}
if(maprow.keySet().size()<sum(maprow.values())||mapcolumn.keySet().size()<sum(mapcolumn.values())||mapblock.keySet().size()<sum(mapblock.values())){
return false;
}
}
return true;
}
public int sum(Collection<Integer> collection){
int result =0;
for(int i:collection){
result+=i;
}
return result;
}
}
四、存在问题
- 每次执行外圈循环,都需要初始化三个哈希表,对不同的行、列、块进行判断求解
- 需要`` import java.util.Collection
- 判断条件冗杂
五、优解代码
class Solution {
public boolean isValidSudoku(char[][] board) {
for(int i =0;i<9;i++){
int row =0;
int column =0;
int block =0;
for(int j =0;j<9;j++){
int rowCurrent = (int)board[i][j] - (int)'0';
int columnCurrent = (int)board[j][i] - (int)'0';
int blockCurrent = (int)board[3*(i/3)+j/3][3*(i%3)+j%3] - (int)'0';
if(rowCurrent > 0){
row = sodokuer(rowCurrent,row);
}
if(columnCurrent > 0){
column = sodokuer(columnCurrent,column);
}
if(blockCurrent > 0){
block = sodokuer(blockCurrent,block);
}
if(row ==-1||column ==-1||block ==-1){
return false;
}
}
}
return true;
}
public int sodokuer(int n,int value){
return ((value>>n) & 1) ==1?-1:value ^(1<<n);
}
}
六、优解思路
- 使用一个长度大于9的二进制数字,存储1-9出现的情况,为1,代表该数字已出现,反之为0。
- 将 存储值value右移n(当前遍历到的数字)位,和1做与运算,即 步骤1 的具体实现,为什么是value右移n位,而不是1左移n位?(意义相同),但因为value右移n位和1 做与运算,若重复出现,结果正好为1,方便用数字1判断
- 如果n已然出现过,则结果返回-1,继而返回false,程序完成
- 如果n未出现,则需要将n存储在存储值的对应位上,该想法可以用
原存储值与 1左移n位 做 异或运算实现
- 内圈for循环开始前,首先重置存储值,且对于 块 的判断:
3*(i/3)+j/3代表第几个块
3*(i%3)+j%3代表该块第几个元素