0037_Sudoku Solver

来源:互联网 发布:alias vred软件下载 编辑:程序博客网 时间:2024/06/08 01:49

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.

题干
A sudoku puzzle…
答案

…and its solution numbers marked in red.

JAVA

方法一

  直接使用递归暴力解题,一开始以为会超时,没想到不但AC了,而且效率在前1/5,只需要注意好边界条件即可。
  第一次在编译器上跑的时候,由于偷懒,在判断数字是否用过时,在一个循环中同时判断横竖两个方向,导致判断不全,如下

        for (int i = 0; i < MAXSIZE; i++) {            if (board[row][i] == '.') {                continue;            } else {                used[board[row][i] - '0'] = true;            }            if (board[i][column] == '.'){                continue;            }            else {                used[board[i][column] - '0'] = true;            }        }

  在这种情况下,当横向判断执行了continue时,就不会判断纵向了,导致可用数字的范围扩大。所以偷懒不能太过分。。。

  在本地测试的时候,为了找错,写了输出语句,同时将sysout重定向到本地文件中,方便查找问题。在下列代码中已经注释掉输出部分。

public class Solution {    static int MAXSIZE = 9;    static int SUBBOXSIZE = 3;    public void solveSudoku(char[][] board) {        if (board.length != MAXSIZE || board[0].length != MAXSIZE){            return ;        }        fillBoard(board,0,0);//        for (int i = 0; i < MAXSIZE; i++) {//            for (int j = 0; j < MAXSIZE; j++) {//                System.out.print(board[i][j] + " ");//            }//            System.out.println();//        }    }    public boolean fillBoard(char[][] board,int startRow, int startCloumn){        if (startRow == MAXSIZE && startCloumn == MAXSIZE) {            return true;        }//          找第一个需要填数字的空格        int row = startRow;        int column = startCloumn;        boolean findEmptyCell = false;        while (row < MAXSIZE) {            while (column < MAXSIZE) {                if (board[row][column] == '.') {                    findEmptyCell = true;                    break;                } else {                    ++column;                }            }            if (findEmptyCell) {                break;            } else {                ++row;                column = 0;            }        }        if (!findEmptyCell) {            return true;        }//        找出在该空格可填写的数字有哪些,若有重复数字说明已经不满足数独条件//        uesd设置为10可以使下标与数独中的数字一一对应        boolean [] used = new boolean[10];        for (int i = 0; i < MAXSIZE; i++) {            if (board[row][i] == '.') {                continue;            } else {                used[board[row][i] - '0'] = true;            }        }        for (int i = 0; i < MAXSIZE; i++) {            if (board[i][column] == '.'){                continue;            }            else {                used[board[i][column] - '0'] = true;            }        }//        获取subbox的左上角坐标        int subBoxRow = row / 3 * 3;        int cubBoxColmun = column / 3 * 3;        for (int i = 0; i < 3; ++i){            for (int j = 0; j < 3; j++) {                if (board[subBoxRow + i][cubBoxColmun + j] == '.'){                    continue;                }                else {                    used[board[subBoxRow + i][cubBoxColmun + j] - '0'] = true;                }            }        }//        填写未使用的数字并递归判断,因为下一层可以填写的数字范围会重新计算,所以对于本次填写不符合条件的数字,不需要重新设置为false        for (int i = 1; i <= MAXSIZE ; i++) {            if(used[i]) {                continue;            }else {                board[row][column] = (char)( '0' + i);//                System.out.println("row = " + row + "\tcolumn = " + column);//                for (int k = 0; k < MAXSIZE; k++) {//                    for (int j = 0; j < MAXSIZE; j++) {//                        System.out.print(board[k][j] + " ");//                    }//                    System.out.println();//                }//                System.out.println();//                System.out.println();                if (fillBoard(board,row,column)){                    return true;                }            }        }        board[row][column] = '.';        return false;    }}
原创粉丝点击