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 36 Valid SudokuLeetCode
- LeetCode 37. 解數獨LeetCode
- 036 Valid Sudoku
- leetcode37 解數獨問題 hardLeetCode
- sudoku 數獨 XY-ChainsAI
- (8)caffe總結之solver及其配置
- Variational Quantum Linear Solver 的MindQuantum復現
- 【Caffe篇】--Caffe solver層從初始到應用
- Ceres Solver: 高效的非線性優化庫(一)優化
- vue37Vue
- 實驗37
- Ceres Solver: 高效的非線性優化庫(二)實戰篇優化
- 《HelloGitHub》第 37 期Github
- 37 機器人機器人
- linux每日命令(37):top命令Linux
- sqli-Labs————less-37SQL
- 37_常用命令
- 每週分享第 37 期
- Study Plan For Algorithms - Part37Go
- Django(37)配置django日誌Django
- 都市,女性︱如意悟真記(37)
- 專案微管理37 - 陣痛
- PostgreSQL DBA(37) - PG 12 REINDEX CONCURRENTLYSQLIndex
- 第37篇 JVM調優方式JVM
- 遊記:第37屆校賽
- 每日一練(37):實現 strStr()
- 「 iOS知識小集 」2018 · 第 37 期iOS
- Oracle OCP(37):Database 體系結構OracleDatabase
- redis自學(37)叢集伸縮Redis
- Tkinter (37) 分隔器部件 ttk.Separator
- Educational Codeforces Round 37 (Rated for Div. 2)
- 程式猿生存指南-37 你好,清華
- 5.16安卓開發日記37安卓
- RCE——web29-32,web37Web
- 【LeetCode】如何學習LeetCode?LeetCode
- 2018-11-4RetailUnwrapped-Adobe2018HolidayPredictions-37AIAPP
- Solidity語言學習筆記————37、Using forSolid筆記
- [case37]聊聊lettuce的shareNativeConnection引數