编写一个程序,通过已填充的空格来解决数独问题。
一个数独的解法需遵循如下规则:
数字 1-9 在每一行只能出现一次。 数字 1-9 在每一列只能出现一次。 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。
空白格用 ‘.’ 表示。一个数独。
答案被标成红色。
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/sudoku-solver
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
先把我的运行超时代码沾上
void solveSudoku(char** board, int boardSize, int* boardColSize){
int i,j;
int di=0;
int mark;
bool a[9][9];
int b[100]={0};
for(int k =0;k<9;k++)
{
for(int l =0;l<9;l++)
{
if(board[k][l]=='.')
{
a[k][l]=false;
b[k++]=k*10+l;
}
else
{
a[k][l]=true;
}
}
}
for(i =0;i<9;i++)
{
for( j =0;j<9;j++)
if(board[i][j]=='.')
{
board[i][j]=1;
break;
}
if(j!=9)
break;
}
while(1)
{
for(int m=0;m<9;m++)
{if(board[i][m]==board[i][j]&&m!=j)
mark=0;}
if(mark==1){
for(int m=0;m<9;m++)
{if(board[m][j]==board[i][j]&&m!=i)
mark=0;}}
if(mark==1)
{
for (int m = (i / 3) * 3; m < (i / 3) * 3 + 3; m++){
for (int n = (j / 3) * 3; n < (j / 3) * 3 + 3; n++){
if (board[m][n] == board[i][j]&&m!=i&&n!=j)
{ mark =0;
break;}
}
}
}
if(mark==1&&i==8&&j==8)
{
return;
}
if(mark==1&&i!=8||j!=8)
{
for(int k =i;k<8;k++)
{
int l;
for( l=j;l<8;l++)
{
if(a[k][l]==false)
{
i=k;
j=l;break;
}
}
if(l!=8)
break;
if(k==7&&l==8)
return;
}
board[i][j]=1; di++; continue;
}
while(board[i][j]==9)
{
a[i][j]=false;
di--;
i=b[di]/10;
j=b[di]%10;
}
board[i][j]=board[i][j]+1;
}
}
怎么说呢?代码是对的,思路是对的,但就是时间复杂度太高!结果就是超出了时间限制!就这还是优化了一定的,我觉得还是回溯的时候是从1到9开始的,每次都是!不灰心不气馁,mmp,再来,参考一下大佬的思路再来!
不知道怎么搞的,非说我有数组越界,真是恶心!怎么改都不对,不改了,写了有一天了,弃了弃了!
void solveSudoku(char** board, int boardSize, int* boardColSize){
int mark=0;
bool rowUsed[9][10]={false};
bool colUsed[9][10]={false};
bool a[9][9];
int i=0;
bool boxUsed[3][3][10]={false};
// 初始化数组
for(int row = 0; row < 9; row++){
for(int col = 0; col < 9; col++) {
int num = board[row][col] - '0';
if(1 <= num && num <= 9){
rowUsed[row][num] = true;
colUsed[col][num] = true;
boxUsed[row/3][col/3][num] = true;
a[row][col]=true;
}
else{
a[row][col]=false;
}
}
}
int col =0;int row=0;
while(1)
{
if(col>8)
{
col=0;
row++;
if(row>8)
{
return;
}
}
if(board[row][col] == '.')
{
if(mark==0) board[row][col]=1;
else board[row][col]=mark;
int num=board[row][col];
bool canUsed = !((colUsed[col][num]||rowUsed[row][num])||boxUsed[row/3][col/3][num]);非说这里越界,我都不知道哪里越界了,问题在colUsed[col][num],但明明是对的,我可是按照大佬的代码改造的,也是醉了
if(canUsed){
rowUsed[row][num] = true;
colUsed[col][num] = true;
boxUsed[row/3][col/3][num] = true;
board[row][col] = (char)('0' + num);
col++;mark=0;continue;
}
else{
for(int m=row;m>=0;m--)
{
int n;
for( n =col;n>=0;n--)
{ if(a[m][n]==false)
{
if(board[m][n]==9)
{
board[m][n]='.';
}
else
{ mark=board[m][n]+1;row=m;col=n; break;}
}}
if(n!=-1)
break;
}
board[row][col]='.';
}
}
else
{
col++;
}
}}
看看我用的大佬的代码,是递归的
class Solution {
public void solveSudoku(char[][] board) {
// 三个布尔数组 表明 行, 列, 还有 3*3 的方格的数字是否被使用过
boolean[][] rowUsed = new boolean[9][10];
boolean[][] colUsed = new boolean[9][10];
boolean[][][] boxUsed = new boolean[3][3][10];
// 初始化
for(int row = 0; row < board.length; row++){
for(int col = 0; col < board[0].length; col++) {
int num = board[row][col] - '0';
if(1 <= num && num <= 9){
rowUsed[row][num] = true;
colUsed[col][num] = true;
boxUsed[row/3][col/3][num] = true;
}
}
}
// 递归尝试填充数组
recusiveSolveSudoku(board, rowUsed, colUsed, boxUsed, 0, 0);
}
private boolean recusiveSolveSudoku(char[][]board, boolean[][]rowUsed, boolean[][]colUsed, boolean[][][]boxUsed, int row, int col){
// 边界校验, 如果已经填充完成, 返回true, 表示一切结束
if(col == board[0].length){
col = 0;
row++;
if(row == board.length){
return true;
}
}
// 是空则尝试填充, 否则跳过继续尝试填充下一个位置
if(board[row][col] == '.') {
// 尝试填充1~9
for(int num = 1; num <= 9; num++){
boolean canUsed = !(rowUsed[row][num] || colUsed[col][num] || boxUsed[row/3][col/3][num]);
if(canUsed){
rowUsed[row][num] = true;
colUsed[col][num] = true;
boxUsed[row/3][col/3][num] = true;
board[row][col] = (char)('0' + num);
if(recusiveSolveSudoku(board, rowUsed, colUsed, boxUsed, row, col + 1)){
return true;
}
board[row][col] = '.';
rowUsed[row][num] = false;
colUsed[col][num] = false;
boxUsed[row/3][col/3][num] = false;
}
}
} else {
return recusiveSolveSudoku(board, rowUsed, colUsed, boxUsed, row, col + 1);
}
return false;
}
}
原理很容易懂,但我改造的就是搞不出来,框架也是对的,可能当局者迷吧!