Leetcode 37 Sudoku Solver
Write a program to solve a Sudoku puzzle by filling the empty cells.
A sudoku solution must satisfy all of the following rules:
- Each of the digits
1-9
must occur exactly once in each row. - Each of the digits
1-9
must occur exactly once in each column. - Each of the the digits
1-9
must occur exactly once in each of the 93x3
sub-boxes of the grid.
Empty cells are indicated by the character '.'
.
A sudoku puzzle...
...and its solution numbers marked in red.
Note:
- The given board contain only digits
1-9
and the character'.'
. - You may assume that the given Sudoku puzzle will have a single unique solution.
- The given board size is always
9x9
.
這個題為Leetcode 36 的變形,在原有的基礎上加上了回溯的方法,主流的方法是使用dfs
1)
class Solution{
public void solveSudoku(char[][] board) {
Set<Character>[] rows = new HashSet[9];
Set<Character>[] columns = new HashSet[9];
Set<Character>[][] boards = new HashSet[3][3];
for(int i=0; i<9; i++){
rows[i]=new HashSet<>();
columns[i]=new HashSet<>();
}
for(int i=0; i<3; i++){
for(int j=0; j<3; j++){
boards[i][j]=new HashSet<>();
}
}
int left=0;
for(int i=0; i<9; i++){
for(int j=0; j<9; j++){
if(board[i][j]=='.') {left++; continue;} //count empty cells
rows[i].add(board[i][j]); //records all available chars in rows
columns[j].add(board[i][j]); //records all available chars in columns
boards[i/3][j/3].add(board[i][j]); //records all available chars in each sub Board
}
}
dfs(rows,columns,boards,board,left);
}
boolean dfs(Set<Character>[] rows, Set<Character>[] columns, Set<Character>[][] boards,char[][] board, int count){
if(count==0) return true; // once count==0 you filled all the empty cells
for(int i=0; i<9; i++){
for(int j=0; j<9; j++){
if(board[i][j]!='.') continue;
for(char digit='1'; digit<='9'; digit++){
if(!rows[i].contains(digit) && !columns[j].contains(digit) && !boards[i/3][j/3].contains(digit)){ // if the character does not exist in this row, column and sub board continue
board[i][j]=digit;
rows[i].add(digit); columns[j].add(digit); boards[i/3][j/3].add(digit);
if(dfs(rows,columns,boards,board,count-1)) return true; // count-1 is number of empty cells left
rows[i].remove(digit); columns[j].remove(digit); boards[i/3][j/3].remove(digit);
board[i][j]='.';
}
}
if(board[i][j]=='.') return false;
}
}
return false;
}
}
2)
class Solution {
class Position {
int x, y;
int v;
Position(int x, int y, int v){
this.x = x;
this.y = y;
this.v = v;
}
}
public void solveSudoku(char[][] board) {
int[][] states = new int[9][];
int i,j,v;
List<Position> values = new ArrayList<Position>(81);
for(i=0; i<9; i++){
states[i] = new int[9];
for(j=0; j<9; j++){
if(board[i][j] !='.'){
v = 1 << (board[i][j] - '0' - 1);
states[i][j] = v ^ 0x01FF;
values.add(new Position(i, j, v));
}
}
}
solve(states, values);
for(i=0; i<9; i++){
for(j=0; j<9; j++){
if(board[i][j] == '.'){
board[i][j] = bit2Char(states[i][j]);
}
}
}
}
boolean solve(int[][] states, List<Position> values){
while(!values.isEmpty()){
Position pos = values.remove(values.size() -1);
int br = pos.x/3*3, bc = pos.y/3*3;
boolean b;
for(int k=0; k<9; k++) {
if(k != pos.y) {
b = setBit(states, pos.x, k, pos.v, values);
if(!b) {
values.clear();
return false;
}
}
if(k != pos.x) {
b = setBit(states, k, pos.y, pos.v, values);
if(!b) {
values.clear();
return false;
}
}
if((br+k/3) != pos.x && (br+k%3) != pos.y){
b = setBit(states, br + k/3, bc + k%3, pos.v, values);
if(!b) {
values.clear();
return false;
}
}
}
}
int leastx = -1, leasty = -1, least = 0;
for(int i=0; i<9; i++){
for(int j=0; j<9; j++){
int bcnt = bitCount(states[i][j]);
if(bcnt!=8 && bcnt > least) {
leastx = i;
leasty = j;
least = bcnt;
}
}
}
if(least != 0){
int i;
int[][] statesClone = new int[9][];
for(i=0; i<9; i++){
statesClone[i] = new int[9];
}
int t= states[leastx][leasty] ^ 0x01FF, s;
while(t>0){
copyArray(states, statesClone);
s = t;
t &= (t-1);
s ^= t;
statesClone[leastx][leasty] = s ^ 0x01FF;
values.add(new Position(leastx, leasty, s));
if(solve(statesClone, values)) {
copyArray(statesClone, states);
return true;
}
}
return false;
} else {
return true;
}
}
boolean setBit(int[][] states, int i, int j , int v, List<Position> values){
if(bitCount(states[i][j]) == 8){ // conflict happening if existed
return (states[i][j] & v) != 0;
}else {
states[i][j] |= v;
if(bitCount(states[i][j]) == 8){
int nv = states[i][j] ^ 0x01FF; // change 1 to 0, 0 to 1 in the last 8 bits;
values.add(new Position(i, j, nv));
}
return true;
}
}
void copyArray(int[][] src, int[][] dest){
for(int i=0; i<9; i++){
System.arraycopy(src[i], 0, dest[i], 0, 9);
}
}
int bitCount(int n){
int count = 0;
while (n>0) {
n &= (n -1) ;
++count;
}
return count;
}
char bit2Char(int bits){
int i = 0;
for(; i<9 && ((1<<i)&bits)!=0; i++);
return (char)(i+1+'0');
}
}
相關文章
- LeetCode 第 37 題 (Sudoku Solver)LeetCode
- Leetcode Sudoku SolverLeetCode
- Leetcode-Sudoku SolverLeetCode
- Sudoku Solver leetcode javaLeetCodeJava
- [LeetCode] Sudoku Solver 求解數獨LeetCode
- Leetcode Valid SudokuLeetCode
- Leetcode 36 Valid SudokuLeetCode
- Leetcode-Valid SudokuLeetCode
- Valid Sudoku leetcode javaLeetCodeJava
- [LeetCode] Valid Sudoku 驗證數獨LeetCode
- 【LeetCode 36_雜湊表】Valid SudokuLeetCode
- leetCode 36. Valid Sudoku(數獨) 雜湊LeetCode
- 【LeetCode從零單排】No36 Valid SudokuLeetCode
- LeetCode #378 JavaScriptLeetCodeJavaScript
- LeetCode | 370 RangeAdditionLeetCode
- leetcode36&37_SudukuSolverLeetCode
- LeetCode 37. 解數獨LeetCode
- [LeetCode] 937. Reorder Log FilesLeetCode
- LeetCode 376. 擺動序列LeetCode
- leetcode 371. Sum of Two IntegersLeetCode
- LeetCode 137 [Single Number II]LeetCode
- 【LeetCode】House Robber III(337)LeetCode
- cryptofbc & ecdlp solver projectsProject
- LeetCode-374-猜數字大小LeetCode
- Leetcode 137. Single Number IILeetCode
- leetcode136-137:single numberLeetCode
- LeetCode137:Single Number IILeetCode
- sudoku 數獨 XY-ChainsAI
- Leetcode——437. 路徑總和 IIILeetCode
- leetcode37 解數獨問題 hardLeetCode
- 371. Sum of Two Integers--LeetCode RecordLeetCode
- (8)caffe總結之solver及其配置
- [LeetCode] 378. Kth Smallest Element in a Sorted MatrixLeetCode
- Leetcode 237. Delete Node in a Linked ListLeetCodedelete
- LeetCode每日一題: 猜數字大小(No.374)LeetCode每日一題
- Leetcode 1375. Bulb Switcher III (python+cpp)LeetCodePython
- 【Caffe篇】--Caffe solver層從初始到應用
- LeetCode 1137第N個斐波那契數LeetCode