您的位置:首页 > 其它

leetcode 37. Sudoku Solver

2016-09-12 11:33 274 查看
Write a program to solve a Sudoku puzzle by filling the empty cells.

Empty cells are indicated by the character ‘.’.

You may assume that there will be only one unique solution.

啊,是上一题的扩展

很快有了一个思路

假设第一行有18种填法 每一行对应下面有若干种填法 那就先试第一行的某种填法 看看合不合法 不合法就直接扔掉 合法就尝试填第二行 递归下去

想下去发现。。。很麻烦。。。

再看看网上的。。。发现时问题分解的粒度不对。。

一行就会很麻烦。。分解成单个位置就会好很多。。。

就是说填一个位置。。看看合不合法 合法填下一个位置。。不合法就停

回溯

这是一个经验:想到的第一个年头 可能思路是对的 但是实现细节(比如这里的粒度是行还是个) 就会很影响代码的实现的复杂难度 所以动手之前先考虑清楚每个细节都是否合适很重要

共有81个位置 ,遍历:
如果当前是最后一个位置 返回true
如果这一位是数字 跳到下一位置
如果这一位是'.' 尝试填上1-9之间的数字 :
如果引起冲突 直接 return false
如果暂时没有引起冲突 递归后面一位的填法 并返回递归结果

"引起冲突"表示新填入的这一位与已经填入的起了冲突


public void solveSudoku(char[][] board) {
solveSudokuWithReturn(board,0);
}

public boolean solveSudokuWithReturn(char[][] board,int index) {
if(index == 81) return true;
else {
int row = index / 9;
int col = index % 9;
if(board[row][col] != '.')
return solveSudokuWithReturn(board, index+1);
else{
for(int tryNum = 1;tryNum <= 9;tryNum++){
board[row][col] = (char) ('0'+tryNum);
if(checkNewPosition(board, index)){
if(solveSudokuWithReturn(board, index+1))
return true;
}
//想了好久这一行是什么意思
//因为比如某次尝试 将这个位置设了值 但是所有尝试都失败了 回到上一层 就会看到每个位置都是有值的 这就没法玩了
//所以如果你条路行不通 那么你尝试完之后就要把所有值复位 这样上一层(上一个位置才能尝试下一个值)
board[row][col] = '.';
}
}
}
return false;
}

public boolean checkNewPosition(char[][] board,int index){
int row = index / 9;
int col = index % 9;
//row
for(int j = 0;j < 9;j++){
if(board[row][j] == board[row][col] && j != col)
return false;
}
//col
for(int i = 0;i < 9;i++){
if(board[i][col] == board[row][col] && i != row)
return false;
}
//block
for(int i = row/3 * 3;i < (row/3 + 1)*3;i++ ){
for(int j = col/3 * 3;j < (col/3+1)*3;j++){
if(board[i][j] == board[row][col] && !(i == row && j == col)){
return false;
}
}
}
return true;
}


回溯法很久没有写过了 每层结束时的状态复原那里一定要注意一下

因为不同层共用一个对象 下层如果改变了对象的状态 上层尝试下一个值时就会看到脏数据
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: