leetcode,解数独算法
这是题目
这是我的解法,用位运算先把已有的数存入row、col、mat,再用深度优先遍历慢慢推算剩下的,时间复杂度大约O(9^3),主要思想就是依次看每个空格能填什么数。
class Solution {
public:
int row[9]={
0};
int col[9]={
0};
int mat[9]={
0};
bool dfs(vector<vector<char>>& board,int x,int y)
{
x+=y/9;
y%=9;
if(x>=9)
return true;
if(board[x][y]!='.')
return dfs(board,x,y+1);
for(int i=0;i<9;i++)
{
int b=3*(x/3)+(y/3);
int v=1<<i;
if(row[x]&v||col[y]&v||mat[b]&v)
continue;
board[x][y]=('1'+i);
row[x]|=v;
col[y]|=v;
mat[b]|=v;
if(dfs(board,x,y+1))
return true;
board[x][y]='.';
row[x]-=v;
col[y]-=v;
mat[b]-=v;
}
return false;
}
void solveSudoku(vector<vector<char>>& board)
{
for(int i=0;i<9;i++)
{
for(int j=0;j<9;j++)
{
if(board[i][j]!='.') row[i]|=(1<<(board[i][j]-'1'));
if(board[j][i]!='.') col[i]|=(1<<(board[j][i]-'1'));
}
int x = (i / 3) * 3;
int y = (i % 3) * 3;
for (int i0 = x; i0 < x+3; i0++)
{
for (int j0 = y; j0 < y+3; j0++)
if(board[i0][j0]!='.') mat[i]|=(1<<board[i0][j0]-'1');
}
}
dfs(board,0,0);
}
};
这是大佬的解法,在时间复杂度上领先我一大截(用时0ms,我用时8ms),主要思想是
//1、某个格子还有可能填上什么数字
//2、某个数字还有可能填在哪些格子
//前期由于已知数较少,一般用第二种方法推理出必填的数。当推理不出新的必填数时,用第一种方法去尝试假设填数
//以下代码在使用第一种方法尝试假设填数时,使用的对象仅为“能排除7个数,只剩下2个数能填”的格子,并且仅设置了一层假设,居然也过了。看了看测试数据才6个,感觉样例有点少,强度也不好评价
class Solution
{
public:
int tryToFill(vector<vector<char>>& board)//这个函数是在推理出了所有必填数而无法再推出更多必填数的时候,开始尝试假设填数而使用的。这个函数内并没有递归,所以假设只有一层。除了在做返回值时的判断,大部分代码和主函数是一样的。以下仅对和主程序不同的部分作注释
{
const int dy[9]={
0,0,0,1,1,1,2,2,2};
const int dx[9]={
0,1,2,0,1,2,0,1,2};
int numsRemain=81;
int previousNumsRemain=81;
int possibleFillPos;
bool rowFilled[9][9];
bool columnFilled[9][9];
bool ninePalaceFilled[9][9];
for (int i=0