C语言回溯算法之解数独(非递归仅供参考)

编写一个程序,通过已填充的空格来解决数独问题。

一个数独的解法需遵循如下规则:

数字 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;
    }
}

原理很容易懂,但我改造的就是搞不出来,框架也是对的,可能当局者迷吧!

发布了37 篇原创文章 · 获赞 1 · 访问量 652

猜你喜欢

转载自blog.csdn.net/zzuzhaohp/article/details/103500218