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;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章