Leetcode--Sudoku Solver(0037)
Posted igoslly
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Leetcode--Sudoku Solver(0037)相关的知识,希望对你有一定的参考价值。
【转载请注明】http://www.cnblogs.com/igoslly/p/8719622.html
来看一下题目:
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. |
题目意思: 完成数独游戏的计算 |
在做这题的前两天,楼主正在摸索华为笔试题的时候,已经写了一个非常直白的实现,具体链接如下:
http://www.cnblogs.com/igoslly/p/8708960.html
不过和原题有些区别:① 所有数据均以字符串形式保存 ② 需要填写的位置以 “.” 代替 0
我们稍稍修改下代码,就可以得到实现方法1:
bool check(int n,char key,vector<vector<char>> num){ for(int i=0;i<9;i++){ int j=n/9; if(num[j][i]==key) { return false; } } for(int i=0;i<9;i++) { int j=n%9; if(num[i][j]==key){return false;} } int x=n/9/3*3; int y=n%9/3*3; for(int i=x;i<x+3;i++){ for(int j=y;j<y+3;j++){ if(num[i][j]==key){return false;} } } return true; } void dfs(int n,vector<vector<char>> &num,bool *sign){ if(n>80) { *sign=true; return; } if(num[n/9][n%9]!=\'.\') { dfs(n+1,num,sign); }else{ for(char i=\'1\';i<=\'9\';i++) { if(check(n,i,num)==true){ num[n/9][n%9]=i; dfs(n+1,num,sign); if(*sign==true) return; } } num[n/9][n%9]=\'.\'; } } class Solution { public: void solveSudoku(vector<vector<char>>& board) { bool sign=false; dfs(0,board,&sign); } };
实现方法2:
优化check函数,将原先逐行、逐列遍历进行判断的方法 → 记录每行、每列、每九宫格是否含有当前数字
具体实施(较原先冗长的代码简短太多):
// line[i][j],column[i][j],subcube[i][j] 分别代表数独每行、每列、每个子单元是否含有数字j(对应1-9) bool line[9][9],column[9][9],subcube[9][9];
进行dfs前,首先要对原题给出的数字进行记录
// 将所有数组置为false memset(line,false,sizeof(line)); memset(column,false,sizeof(column)); memset(subcube,false,sizeof(subcube)); // 根据题意,设定初始数组的值 for(int i=0;i<9;i++){ for(int j=0;j<9;j++){ if(board[i][j]==\'.\') continue; int num=board[i][j]-\'1\'; // 给定题目存在问题,无解,直接返回 int cube=i/3*3 + j/3; if(line[i][num] || column[j][num] || subcube[cube][num]) return ; line[i][num] = column[j][num] = subcube[cube][num] = true; } }
实现方法3:
在实现方法1中,我们使用 n = 0~80 来记录当前填充空格,根据 n 是否越界判断数独填充是否完成。
当然我们也可以采用 i & j / row & col 对位置进行记录,更为直观;
逐行进行填充时,需要对 j > 8 (初始 0)进行换行操作:
// 当j>8时,i++,否则 i 值不变 // 当j>8时,及时取余,重新从0~8计算 (i,j) -> (i+(j+1)/9,(j+1)%9)
具体递归代码:
bool step(vector<vector<char>>&board,int i,int j){ if(i==9) return true; if(board[i][j]!=\'.\') { if(i==8&&j==8){ return true; } else{ return step(board,i+(j+1)/9,(j+1)%9); // step里值表示i,j换行 } } int cube=i/3*3 + j/3; for(int k=0;k<9;k++){ if(line[i][k] || column[j][k] || subcube[cube][k]) continue; line[i][k] = column[j][k] = subcube[cube][k] = true; board[i][j] = \'1\'+k; if(step(board,i+(j+1)/9,(j+1)%9)) // 若数独已完成,直接返回true return true; line[i][k] = column[j][k] = subcube[cube][k] = false; board[i][j] = \'.\'; } return false; }
以上是关于Leetcode--Sudoku Solver(0037)的主要内容,如果未能解决你的问题,请参考以下文章
[leetcode] sudoku solver:暴力还是优化
ceres solver 02 中代价函数和AutoDiffCostFunction的参数顺序