

用回溯算法求解数独问题
source link: http://mp.weixin.qq.com/s?__biz=MzI3NzIzMDY0NA%3D%3D&%3Bmid=2247493684&%3Bidx=1&%3Bsn=4c169cb1451c1a93dc2b37bf1158b1e3
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

// 每日前端夜话 第408篇
// 正文共:1200 字
// 预计阅读时间:5 分钟

前几天我们在《浅析常见的算法范式》中讨论了一些常见的算法范式,但是还留下了回溯算法没有解决。本文来研究回溯算法。
回溯是通过逐步构建解决方案来解决递归问题的算法。通常回溯从可能的解决方案开始,如果它不起作用,则需要回溯并尝试另一种解决方案,直到找到可行的解决方案为止。回溯在解决 CSP(约束满足问题)时特别有用,例如填字游戏、口算题和数独等。
通常回溯算法可用于以下三种类型的问题:
-
需要找到可行解决方案的决策问题
-
需要找到最佳解决方案的优化问题
-
需要找到一组可行解决方案的列举问题
在本文中,我将通过解决数独问题来演示回溯策略。
解决数独问题
针对此类问题的回溯算法会尝试在每个空格中列举所有的数字,直到问题被解决为止。先从 main 方法开始:
function sudokuSolver(matrix) {
if (solveSudoku(matrix) === true) {
return matrix;
}
return '无解';
}
接下来是算法的主要逻辑:
const UNASSIGNED = 0;
function solveSudoku(matrix) {
let row = 0;
let col = 0;
let checkBlankSpaces = false;
// 验证数独是否已解决,如果尚未解决,则获取下一个空格的位置
for (row = 0; row < matrix.length; row++) {
for (col = 0; col < matrix[row].length; col++) {
if (matrix[row][col] === UNASSIGNED) {
checkBlankSpaces = true;
break;
}
}
if (checkBlankSpaces === true) {
break;
}
}
//当没有空格时则意味着已经解决
if (checkBlankSpaces === false) {
return true;
}
// 尝试用正确的数字填充空格
for (let num = 1; num <= 9; num++) {
// isSafe 用于检查在行、列或 3x3 的格子中是否已经存在了数字 num(代码实现在后面)
if (isSafe(matrix, row, col, num)) {
matrix[row][col] = num;
if (solveSudoku(matrix)) {
return true;
}
// 如果 num 所在的位置不合适,需要再次标记为“空格”,然后用不同的 num 回溯
matrix[row][col] = UNASSIGNED;
}
}
return false;
}
接下来看辅助函数的实现:
function isSafe(matrix, row, col, num) {
return (
!usedInRow(matrix, row, num) &&
!usedInCol(matrix, col, num) &&
!usedInBox(matrix, row - (row % 3), col - (col % 3), num)
);
}
function usedInRow(matrix, row, num) {
for (let col = 0; col < matrix.length; col++) {
if (matrix[row][col] === num) {
return true;
}
}
return false;
}
function usedInCol(matrix, col, num) {
for (let row = 0; row < matrix.length; row++) {
if (matrix[row][col] === num) {
return true;
}
}
return false;
}
function usedInBox(matrix, boxStartRow, boxStartCol, num) {
for (let row = 0; row < 3; row++) {
for (let col = 0; col < 3; col++) {
if (matrix[row + boxStartRow][col + boxStartCol] === num) {
return true;
}
}
}
return false;
}
最后对算法进行测试:
const sudokuGrid = [
[5, 3, 0, 0, 7, 0, 0, 0, 0],
[6, 0, 0, 1, 9, 5, 0, 0, 0],
[0, 9, 8, 0, 0, 0, 0, 6, 0],
[8, 0, 0, 0, 6, 0, 0, 0, 3],
[4, 0, 0, 8, 0, 3, 0, 0, 1],
[7, 0, 0, 0, 2, 0, 0, 0, 6],
[0, 6, 0, 0, 0, 0, 2, 8, 0],
[0, 0, 0, 4, 1, 9, 0, 0, 5],
[0, 0, 0, 0, 8, 0, 0, 7, 9]
];
console.log(sudokuSolver(sudokuGrid));
以下是通过回溯法求解数独问题的模拟动画:

希望本文能帮你理解回溯算法,以后我门还会再讨论更多有趣的算法。



前端先锋
长按扫描维码
关注我们 获取更多前端资讯
|最新技术|业界动态|
|学习视频|源码资源|
前端先锋
转了吗
赞了吗
在看吗
Recommend
-
12
晓查 发自 凹非寺 量子位 报道 | 公众号 QbitAI 现在只需拍张照片,就能快速解决数独问题了。 数独对计算机来说不是什么难事,但就是这样一个“平平无奇”的项目却登上了GitHub今日的热榜。 这个登上...
-
28
Dancing Links+Algorithm X求解数独 #include <algorithm>#include <limits>#include <cstdio>#include <cstring>using namespace std;
-
20
回溯算法团灭子集、排列、组合问题 👆让天下没有难刷的算法!若
-
10
回溯算法秒杀数独问题 👆让天下没有难刷的算法!若 GitBook 访问太慢,可尝试
-
9
回溯算法大家是不是已经快忘了,还记得组合问题应该怎么求了么?哈哈哈 回溯算法其实就是暴力搜索,既然是暴力搜索为什么要非要用回溯呢?因为一些问题能暴力搜索出就不错了,找不出更好的办法。 给定两个整数 n 和 k,返回 1 ... n 中所...
-
6
回溯算法牛逼:集合划分问题 培养框架思维,真正爱上算法!关注公众号查看更新文章👆 相关推荐: 读完本文,你不仅学会了算法套路,还可以顺便去 LeetCode 上拿下如下题目:
-
9
2021-04-30 / java
-
6
经典回溯算法:集合划分问题
-
7
【LeetCode回溯算法#07】子集问题I+II,巩固解题模板并详解回溯算法中的去重问题 ...
-
7
【LeetCode回溯算法#10】图解N皇后问题(即回溯算法在二维数组中的应用) ...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK