leetcode--解数独

要求:编写一个程序,通过已填充的空格来解决数独问题。
一个数独的解法需遵循如下规则:

  • 数字 1-9 在每一行只能出现一次。
  • 数字 1-9 在每一列只能出现一次。
  • 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。
    注:空白格用 ‘.’ 表示。
    在这里插入图片描述

解法描述:

  • 约束编程:解数独的一个约束条件是一个数字只能在当前行、当前列和当前的格子中仅能出现一次。这意味这每次放置一个数字都要设置相应的约束。在数独上放置一个数字后立即排除当前行、列和格子对该数字的使用。这会传播 约束条件并有利于减少需要考虑组合的个数。
    在这里插入图片描述
  • 回溯:回溯的思路如下图所示,当我们要添加一个数字在当前行无法再当前位置添加,即当前行或列或格子中存在该数字,那么就进行回溯到前一个位置放置,若前一个也无法放置,那么就继续回溯。
    在这里插入图片描述

算法描述

  • 使用board[i][col]来标识当前列,使用board[row][i]来标识当前行,使用 board [3 * intval(row / 3) + intval(i / 3)][3 * intval(col / 3) + intval(i % 3)]来标识当前格子
  • 现在准备好写回溯函数了:
//分析
backtrack(row = 0, col = 0){
	从最左上角的方格开始 row = 0, col = 0。直到到达当前行最后一个位置。
	从19 迭代循环数组,尝试放置数字 d 进入 (row, col) 的位置。
		如果数字 d 还没有出现在当前行,列和格子中:
			将 d 放入 (row, col) 位置中。记录下 d 已经出现在当前行,列和格子中。
			如果这是最后一个格子row == 8, col == 81. 意味着已经找出了数独的解。
			否则:
				放置接下来的数字。
			如果数独的解还没找到:
				将最后的数从 (row, col) 移除
		如果数字 d 有出现在当前行或列或格子中:
			回溯到前一个 (row, col - 1)位置,即将尝试位置重置为'.'

//代码			
class Solution {
    /**
     * @param String[][] $board
     * @return NULL
     */
    
    function solveSudoku(&$board) {
        $this->backtrack($board);
    }
    //验证放入位置是否合法
    function isValid($board, $row, $col, $num) {
        for ($i = 0; $i < 9; $i++) {
            if ($board[$i][$col] == $num) {
                return false;
            }
            if ($board[$row][$i] == $num) {
                return false;
            }
            if ($board[3 * intval($row / 3) + intval($i / 3)][3 * intval($col / 3) + intval($i % 3)] == $num) {
                return false;
            }
        }
        return true;
    }
    //回溯函数
    function backtrack(&$board){
        for ($i = 0; $i < 9; $i++) {
            for ($j = 0; $j < 9; $j++) {
                if ($board[$i][$j] == '.') {
                    for ($num = 1; $num <= 9; $num++) {
                        $ch = strval($num);
                        if ($this->isValid($board, $i, $j, $ch)) {
                            $board[$i][$j] = $ch;
                            if ($this->backtrack($board)) {
                                return true;
                            } else {
                                $board[$i][$j] = '.';
                            }
                        }
                    }
                    return false;
                }
            }
        }
        return true;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章