Write a program to solve a Sudoku puzzle by filling the empty cells.

A sudoku solution must satisfy all of the following rules:

  1. Each of the digits 1-9 must occur exactly once in each row.
  2. Each of the digits 1-9 must occur exactly once in each column.
  3. Each of the the digits 1-9 must occur exactly once in each of the 9 3x3 sub-boxes of the grid.

Empty cells are indicated by the character '.'.


A sudoku puzzle...


...and its solution numbers marked in red.

Note:

    • The given board contain only digits 1-9and the character '.'.
    • You may assume that the given Sudoku puzzle will have a single unique solution.
    • The given board size is always 9x9.

这道求解数独的题是在之前那道 Valid Sudoku 的基础上的延伸,之前那道题让我们验证给定的数组是否为数独数组,这道让求解数独数组,跟此题类似的有 PermutationsCombinationsN-Queens 等等,其中尤其是跟 N-Queens 的解题思路及其相似,对于每个需要填数字的格子带入1到9,每代入一个数字都判定其是否合法,如果合法就继续下一次递归,结束时把数字设回 '.',判断新加入的数字是否合法时,只需要判定当前数字是否合法,不需要判定这个数组是否为数独数组,因为之前加进的数字都是合法的,这样可以使程序更加高效一些,整体思路是这样的,但是实现起来可以有不同的形式。一种实现形式是递归带上横纵坐标,由于是一行一行的填数字,且是从0行开始的,所以当i到达9的时候,说明所有的数字都成功的填入了,直接返回 ture。当j大于等于9时,当前行填完了,需要换到下一行继续填,则继续调用递归函数,横坐标带入 i+1。否则看若当前数字不为点,说明当前位置不需要填数字,则对右边的位置调用递归。若当前位置需要填数字,则应该尝试填入1到9内的所有数字,让c从1遍历到9,每当试着填入一个数字,都需要检验是否有冲突,使用另一个子函数 isValid 来检验是否合法,假如不合法,则跳过当前数字。若合法,则将当前位置赋值为这个数字,并对右边位置调用递归,若递归函数返回 true,则说明可以成功填充,直接返回 true。不行的话,需要重置状态,将当前位置恢复为点。若所有数字都尝试了,还是不行,则最终返回 false。检测当前数组是否合法的原理跟之前那道 Valid Sudoku 非常的相似,但更简单一些,因为这里只需要检测新加入的这个数字是否会跟其他位置引起冲突,分别检测新加入数字的行列和所在的小区间内是否有重复的数字即可,参见代码如下:

解法一:

class Solution {
public:
void solveSudoku(vector<vector<char>>& board) {
helper(board, , );
}
bool helper(vector<vector<char>>& board, int i, int j) {
if (i == ) return true;
if (j >= ) return helper(board, i + , );
if (board[i][j] != '.') return helper(board, i, j + );
for (char c = ''; c <= ''; ++c) {
if (!isValid(board, i , j, c)) continue;
board[i][j] = c;
if (helper(board, i, j + )) return true;
board[i][j] = '.';
}
return false;
}
bool isValid(vector<vector<char>>& board, int i, int j, char val) {
for (int x = ; x < ; ++x) {
if (board[x][j] == val) return false;
}
for (int y = ; y < ; ++y) {
if (board[i][y] == val) return false;
}
int row = i - i % , col = j - j % ;
for (int x = ; x < ; ++x) {
for (int y = ; y < ; ++y) {
if (board[x + row][y + col] == val) return false;
}
}
return true;
}
};

还有另一种递归的写法,这里就不带横纵坐标参数进去,由于递归需要有 boolean 型的返回值,所以不能使用原函数。因为没有横纵坐标,所以每次遍历都需要从开头0的位置开始,这样无形中就有了大量的重复检测,导致这种解法虽然写法简洁一些,但击败率是没有上面的解法高的。这里的检测数组冲突的子函数写法也比上面简洁不少,只用了一个 for 循环,用来同时检测行列和小区间是否有冲突,注意正确的坐标转换即可,参见代码如下:

解法二:

class Solution {
public:
void solveSudoku(vector<vector<char>>& board) {
helper(board);
}
bool helper(vector<vector<char>>& board) {
for (int i = ; i < ; ++i) {
for (int j = ; j < ; ++j) {
if (board[i][j] != '.') continue;
for (char c = ''; c <= ''; ++c) {
if (!isValid(board, i, j, c)) continue;
board[i][j] = c;
if (helper(board)) return true;
board[i][j] = '.';
}
return false;
}
}
return true;
}
bool isValid(vector<vector<char>>& board, int i, int j, char val) {
for (int k = ; k < ; ++k) {
if (board[k][j] != '.' && board[k][j] == val) return false;
if (board[i][k] != '.' && board[i][k] == val) return false;
int row = i / * + k / , col = j / * + k % ;
if (board[row][col] != '.' && board[row][col] == val) return false;
}
return true;
}
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/37

类似题目:

Valid Sudoku

Unique Paths III

参考资料:

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

https://leetcode.com/problems/sudoku-solver/discuss/15853/Simple-and-Clean-Solution-C%2B%2B

https://leetcode.com/problems/sudoku-solver/discuss/15752/Straight-Forward-Java-Solution-Using-Backtracking

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] 37. Sudoku Solver 求解数独的更多相关文章

  1. [leetcode]37. Sudoku Solver 解数独

    Write a program to solve a Sudoku puzzle by filling the empty cells. A sudoku solution must satisfy  ...

  2. leetcode 37. Sudoku Solver 36. Valid Sudoku 数独问题

    三星机试也考了类似的题目,只不过是要针对给出的数独修改其中三个错误数字,总过10个测试用例只过了3个与世界500强无缘了 36. Valid Sudoku Determine if a Sudoku ...

  3. LeetCode 37 Sudoku Solver(求解数独)

    题目链接: https://leetcode.com/problems/sudoku-solver/?tab=Description   Problem : 解决数独问题,给出一个二维数组,将这个数独 ...

  4. [LeetCode] Sudoku Solver 求解数独

    Write a program to solve a Sudoku puzzle by filling the empty cells. Empty cells are indicated by th ...

  5. Java [leetcode 37]Sudoku Solver

    题目描述: Write a program to solve a Sudoku puzzle by filling the empty cells. Empty cells are indicated ...

  6. [leetcode 37]sudoku solver

    1 题目: 根据给出的数独,全部填出来 2 思路: 为了做出来,我自己人工做了一遍题目给的数独.思路是看要填的数字横.竖.子是否已经有1-9的数字,有就剔除一个,最后剩下一个的话,就填上.一遍一遍的循 ...

  7. leetcode 37 Sudoku Solver java

    求数独,只要求做出一个答案就可以. 刚开始对题意理解错误,以为答案是唯一的, 所以做了很久并没有做出来,发现答案不唯一之后,使用回溯.(还是借鉴了一下别人) public class Solution ...

  8. [Leetcode][Python]37: Sudoku Solver

    # -*- coding: utf8 -*-'''__author__ = 'dabay.wang@gmail.com' 37: Sudoku Solverhttps://oj.leetcode.co ...

  9. LeetCode:Valid Sudoku,Sudoku Solver(数独游戏)

    Valid Sudoku Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules. The Sudoku bo ...

随机推荐

  1. 利用 Javascript 让 DIV 自适应屏幕的分辨率,从而决定是否显示滚动条

    直接贴代码了: <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> < ...

  2. centos6 升级Git版本

    操作步骤如下: yum remove -y git #卸载旧版本Git yum install -y tk zlib-devel openssl-devel perl cpio expat-devel ...

  3. Spring源码系列 — 注解原理

    前言 前文中主要介绍了Spring中处理BeanDefinition的扩展点,其中着重介绍BeanDefinitionParser方式的扩展.本篇文章承接该内容,详解Spring中如何利用BeanDe ...

  4. 带你认识MySQL sys schema

    前言:  MySQL 5.7中引入了一个新的sys schema,sys是一个MySQL自带的系统库,在安装MySQL 5.7以后的版本,使用mysqld进行初始化时,会自动创建sys库. sys库里 ...

  5. JQ动态生成节点绑定事件无效问题

    最近做项目的时候遇见了一个问题,通过jq将动态节点绑定到dom节点上,并且为动态节点绑定方法,此方法再次为动态节点添加动态节点,但在刷新之后,动态节点上的方法失效了,过程为:创建动态节点->动态 ...

  6. Python struct与小端存储

    参考链接:https://www.liaoxuefeng.com/wiki/1016959663602400/1017685387246080 在使用Python 实现字符向字节数据类型转换的时候,P ...

  7. java 学习 进阶之 一 (线程基础)

    一.线程安全 线程安全的概念:当多个线程访问某一个类(对象或方法)时.这个类始终都能表现出正确的行为那么这个类(对象或方法)就是线程安全的. synchronized:可以在任何对象及方法上加锁,而加 ...

  8. Python基础22

    数据类型可变不可变,说的是“指向”. 深浅拷贝.

  9. Linux文件共享服务 FTP,NFS 和 Samba

    Linux 系统中,存储设主要有下面几种: DAS DAS 指 Direct Attached Storage,即直连附加存储,这种设备直接连接到计算机主板总线上,计算机将其识别为一个块设备,例如常见 ...

  10. 前端开发CSS3——文本样式和盒子及样式

    博主废话少说,直接介绍css常用的属性和属性值:属性和值只需过一遍,页面的结构还是需要布局,布局的只是后期会更新的. 提供一些图标的网站:font-awesome:     http://fontaw ...