1. 程式人生 > 其它 >Leetcode 解數獨

Leetcode 解數獨

技術標籤:leetcode題集leetcode

解數獨

題目描述:

編寫一個程式,通過填充空格來解決數獨問題。

一個數獨的解法需遵循如下規則:

數字 1-9 在每一行只能出現一次。
數字 1-9 在每一列只能出現一次。
數字 1-9 在每一個以粗實線分隔的 3x3 宮內只能出現一次。

提示:
1.給定的數獨序列只包含數字 1-9 和字元 '.' 。
2.你可以假設給定的數獨只有唯一解。
3.給定數獨永遠是 9x9 形式的。

空白格用 '.' 表示。
以下答案標記為紅色。

在這裡插入圖片描述
在這裡插入圖片描述

題目連結

class Solution {
    private boolean[][] digit;
private char[][] result; private boolean[][] row; private boolean[][] col; private boolean[][] block; private boolean end; public void solveSudoku(char[][] board) { // 回溯演算法 // 初始化 this.digit = new boolean[9][9]; this.result = board; this.
row = new boolean[9][10]; this.col = new boolean[9][10]; this.block = new boolean[9][10]; for(int i = 0 ; i<9 ;i++){ for(int j = 0 ; j<9 ;j++){ if(board[i][j] != '.'){ int temp = (int)(board[i][j] - '0'); row[
i][temp] = true; col[j][temp] = true; block[3*(i/3)+j/3][temp] = true; digit[i][j] = true; } } } DFS(0,0); // 從第一行第一列開始 } public void DFS(int x,int y){ if(x<8 && y == 9){ DFS(x+1,0); return; } if(x == 8 && y == 9){ end = true; return; } for(int i=1 ; i<=9 && !end; i++){ // 遍歷當前位置需要填入的值 這裡有坑:一定注意end標記要放再這裡!否則會被覆蓋修改! if(!digit[x][y]){ // 當前位置不為固定數字 if(check(x,y,i)){ // 判斷當前位置是否符合規則 row[x][i] = true; col[y][i] = true; block[3*(x/3)+y/3][i] = true; result[x][y] = (char)(i+'0'); DFS(x,y+1); // 對下一列空格位置遞迴 row[x][i] = false; col[y][i] = false; block[3*(x/3)+y/3][i] = false; } }else{ // 當前位置為固定數字 DFS(x,y+1); return; } } } public boolean check(int r,int c,int n){ if(row[r][n] || col[c][n] || block[3*(r/3)+c/3][n]){ // 行判斷、列判斷和塊判斷 return false; } return true; } }

能簡單地想到,這是一個典型的回溯法例題,首先按照行優先,每次對一個空格進行1到9的遍歷,如果不符合規則,則繼續遍歷剩餘的數字,否則對下一個空格再次執行同樣的操作,當達到結束條件時。第一個需要注意地是:每次的當前規則都要還原操作;第二個需要注意地是:這個結束體一定只能執行一次!否則會發生覆蓋!所以要在for上新增提前結束的條件,而不能在for迴圈外面。如果讀者對回溯演算法還是有些偏難理解,可以先嚐試徹底解決八皇后問題,因為一般的回溯演算法都是八皇后問題的變體,只要掌握了八皇后問題,一般這樣的問題就都能迎刃而解。