求解数独回溯算法

实现的java代码如下(该算法只是将结果打印输出,并没有对原数组实现更改):

    //判断a[i][j]取值val是否有效
    public boolean isValid(int[][] a, int i, int j, int val){
        //判断是否跟同行冲突
        for(int j1=0;j1<9;j1++){
            if(a[i][j1]==val)
                return false;
        }
        //判断是否跟同列冲突
        for(int i1=0;i1<9;i1++){
            if(a[i1][j]==val)
                return false;
        }
        //找出a[i][j]所在的九宫格
        int i1 = 0, j1 = 0;
        boolean flag = true;
        for(i1=0;i1<3&&flag;i1++){
            if(!(i>=i1*3&&i<3*(i1+1)))
                continue;
            for(j1=0;j1<3;j1++){
                if(j>=j1*3&&j<3*(j1+1)){
                    flag = false;
                    break;
                }
            }
        }
        i1--;
        //判断值是否跟所在九宫格冲突
        for(int i2=3*i1;i2<3*(i1+1);i2++){           
            for(int j2=3*j1;j2<3*(j1+1);j2++){
                if(a[i2][j2]==val)
                    return false;
            }
        }
        return true;
    }
    //打印数独
    public void printMatrix(int[][] a){
        for(int i=0;i<9;i++){
            for(int j=0;j<9;j++){
                System.out.print(a[i][j]+" ");
            }
            System.out.println();
        }
    }
    //回溯法求解数独
    public void shuDu(int[][] a, int i, int j){
        if(i==8&&j>=9){
            printMatrix(a);
            return;
        }
        if(j==9){
            j=0;
            i++;
        }
        if(a[i][j]==0){
            for(int k=1;k<=9;k++){
                if(isValid(a,i,j,k)){
                    a[i][j] = k;
                    //向下继续找
                    shuDu(a,i,j+1);
                    //如果没有找到全部答案将a[i][j]的值恢复
                    a[i][j] = 0;
                }
            }
        }else{
            shuDu(a,i,j+1);
        }
    }

算法调用示例如下:

public static void main(String[] args) {
                Solution solu = new Solution();
        int ma1[][]={
                 {0,3,0,0,0,5,0,6,0},
                 {0,1,0,0,0,3,0,8,0},
                 {0,4,0,0,0,0,0,0,7},
                 {0,0,7,0,2,4,0,0,0},
                 {5,0,0,0,9,0,0,0,0},
                 {0,8,0,3,0,0,5,0,0},
                 {0,0,0,8,0,0,0,0,0},
                 {0,0,9,0,0,0,0,7,3},
                 {0,5,0,9,0,0,0,0,2}};
        int[][] sudoku = { 
                 {8,0,0,0,0,0,0,0,0}, 
                 {0,0,3,6,0,0,0,0,0}, 
                 {0,7,0,0,9,0,2,0,0}, 
                 {0,5,0,0,0,7,0,0,0}, 
                 {0,0,0,0,4,5,7,0,0}, 
                 {0,0,0,1,0,0,0,3,0}, 
                 {0,0,1,0,0,0,0,6,8},  
                 {0,0,8,5,0,0,0,1,0}, 
                 {0,9,0,0,0,0,4,0,0}};
        solu.shuDu(sudoku, 0, 0);
}            

 不进行打印,实现更改数组的改进算法(数组为字符数组,可根据需要进行更改):

public class Solution {
    //判断a[i][j]取值val是否有效
    public boolean isValid(char[][] a, int i, int j, char val){
        //判断是否跟同行冲突
        for(int j1=0;j1<9;j1++){
            if(a[i][j1]==val)
                return false;
        }
        //判断是否跟同列冲突
        for(int i1=0;i1<9;i1++){
            if(a[i1][j]==val)
                return false;
        }
        //找出a[i][j]所在的九宫格
        int i1 = 0, j1 = 0;
        boolean flag = true;
        for(i1=0;i1<3&&flag;i1++){
            if(!(i>=i1*3&&i<3*(i1+1)))
                continue;
            for(j1=0;j1<3;j1++){
                if(j>=j1*3&&j<3*(j1+1)){
                    flag = false;
                    break;
                }
            }
        }
        i1--;
        //判断值是否跟所在九宫格冲突
        for(int i2=3*i1;i2<3*(i1+1);i2++){           
            for(int j2=3*j1;j2<3*(j1+1);j2++){
                if(a[i2][j2]==val)
                    return false;
            }
        }
        return true;
    } 
    //回溯法求解数独
    public boolean shuDu(char[][] a, int i, int j){
        if(i==8&&j>=9){
            return true;
        }
        if(j==9){
            j=0;
            i++;
        }
        if(a[i][j]=='.'){
            char ch = '1';
            for(int k=0;k<9;k++){
                if(isValid(a,i,j,(char)(ch+k))){
                    a[i][j] = (char) (ch+k);
                    //向下继续找
                    if(shuDu(a,i,j+1))
                        return true;
                    //如果没有找到全部答案将a[i][j]的值恢复
                    a[i][j] = '.';
                }
            }
        }else{
            if(shuDu(a,i,j+1))
                return true;
        }
        return false;
    }
    
    public void solveSudoku(char[][] board) {
        shuDu(board, 0, 0);
    }
}

算法调用示例如下:

public class Main {

public static void main(String[] args) {
Solution solu = new Solution();
char[][] sudoku = {
{'8','.','.','.','.','.','.','.','.'},
{'.','.','3','6','.','.','.','.','.'},
{'.','7','.','.','9','.','2','.','.'},
{'.','5','.','.','.','7','.','.','.'},
{'.','.','.','.','4','5','7','.','.'},
{'.','.','.','1','.','.','.','3','.'},
{'.','.','1','.','.','.','.','6','8'},
{'.','.','8','5','.','.','.','1','.'},
{'.','9','.','.','.','.','4','.','.'}};
long start = System.nanoTime();
solu.solveSudoku(sudoku);
long time = System.nanoTime() - start;
System.out.println(time);
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
System.out.print(sudoku[i][j]+" ");
}
System.out.println();
}
}
}
原文地址:https://www.cnblogs.com/gaopeng527/p/4873447.html