做者:Christina翻译:疯狂的技术宅javascript
原文:https://dev.to/christinamcmah...前端
未经容许严禁转载java
前几天咱们在《浅析常见的算法范式》中讨论了一些常见的算法范式,可是还留下了回溯算法没有解决。本文来研究回溯算法。程序员
回溯是经过逐步构建解决方案来解决递归问题的算法。一般回溯从可能的解决方案开始,若是它不起做用,则须要回溯并尝试另外一种解决方案,直到找到可行的解决方案为止。回溯在解决 CSP(约束知足问题)时特别有用,例如填字游戏、迷宫和数独等。面试
一般回溯算法可用于如下三种类型的问题:算法
在本文中,我将经过解决数独问题来演示回溯策略。segmentfault
针对此类问题的回溯算法会尝试在每一个空格中列举全部的数字,直到问题被解决为止。先从 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));
如下是经过回溯法求解数独问题的模拟动画:
但愿本文能帮你理解回溯算法,之后我门还会再讨论更多有趣的算法。