码迷,mamicode.com
首页 > 其他好文 > 详细

Sudoku Solver

时间:2015-04-12 22:20:39      阅读:128      评论:0      收藏:0      [点我收藏+]

标签:

https://leetcode.com/problems/sudoku-solver/

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.

解题思路:

这道题要求可能的解,可以想到用回溯。但是题目讲到,可能的解只有一个,我们只需要把这一个求出来就可以了。

1. 这里我们用了三个set数组,分别记录每行、每列和每个3*3的小格子里已经有的数组。这样,新选择的数字就不能和它们重复。这三组set用来作为递归的剪枝条件。

2. 原来的board是二维的,这里我仍然使用大多数dfs方法中常用的step变量来计数。这样就要算和step对应的行数、列数,以及3*3的小格子的index。

3. 也是最关键的。本题要找到的是唯一的解,而且要求回写到board中的。这样dfs函数就不能是void了。为什么?因为void一般是有另一个变量记录所有可能的解,不断的递归、回溯的同时,将解塞进这个变量里。最后看这个变量的内容即可。但是这里,board是同时要回溯的。如果void,找到可能的解后,dfs还是要回溯。这样,整个方法递归完成,board无论如何是要回到原样的。也就是说,做了半天等于没做。

那么,如何解决?

我们这里用了一个比较通用的方法,也是以后遇到这类问题可以采用的方法。就是将dfs的返回值改为boolean。如果dfs的返回值为true,也就是说是一个可能的解,那么就不用回溯了,否则才回溯。这样,找到一个可能的解,就直接返回true了,递归也不会再进行下去。于是,board就可以保留唯一的解的状态,直接返回。

public class Solution {
    public void solveSudoku(char[][] board) {
        Set<Character>[] rowSet = new HashSet[board.length];
        Set<Character>[] columnSet = new HashSet[board.length];
        Set<Character>[] squareSet = new HashSet[(board.length / 3) * (board.length / 3)];
        //初始化行set、列set和小squareSet
        for(int i = 0; i < board.length; i++) {
            rowSet[i] = new HashSet<Character>();
            for(int j = 0; j < board.length; j++) {
                if(i == 0) {
                    columnSet[j] = new HashSet<Character>();
                }
                
                int squareIndex = (i / 3) * (board.length / 3) + (j / 3);
                if(squareSet[squareIndex] == null) {
                    squareSet[squareIndex] = new HashSet<Character>(); 
                }
                if(board[i][j] != ‘.‘) {
                    rowSet[i].add(board[i][j]);
                    columnSet[j].add(board[i][j]);
                    squareSet[squareIndex].add(board[i][j]);
                }
            }
        }
        dfs(board, rowSet, columnSet, squareSet, 0);
    }
    
    public boolean dfs(char[][] board, Set<Character>[] rowSet, Set<Character>[] columnSet, Set<Character>[] squareSet, int step) {
        if(step == board.length * board.length) {
            return true;
        }
        int row = step / board.length;
        int column = step % board.length;
        int squareIndex = (row / 3) * (board.length / 3) + (column / 3);
        if(board[row][column] != ‘.‘) {
            return dfs(board, rowSet, columnSet, squareSet, step + 1);
        } else {
            for(int i = 1; i < 10; i++) {
                char temp = (char)(‘0‘ + i);
                if(!rowSet[row].contains(temp) && !columnSet[column].contains(temp) && !squareSet[squareIndex].contains(temp)) {
                    board[row][column] = temp;
                    rowSet[row].add(temp);
                    columnSet[column].add(temp);
                    squareSet[squareIndex].add(temp);
                    if(dfs(board, rowSet, columnSet, squareSet, step + 1)) {
                        return true;
                    }
                    board[row][column]= ‘.‘;
                    rowSet[row].remove(temp);
                    columnSet[column].remove(temp);
                    squareSet[squareIndex].remove(temp);
                }
            }
        }
        return false;
    }
}

 

Sudoku Solver

标签:

原文地址:http://www.cnblogs.com/NickyYe/p/4420629.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!