題目
題目有點長,直接放上 LeetCode 連結:
https://leetcode.com/problems/sudoku-solver/
簡單來說就是要做一個自動產生數獨解答的程式。
題目會輸入一個二維陣列,數獨題目空白的地方會用”.”代替,
我們則要將數獨的答案填完回傳。
輸入的數獨題目,一定會有一個唯一解,所以不需要考慮題目有錯誤或是多重解答的情況。
解題過程
- 從第一個空白格開始找可能的數字填上(行列和九宮格皆不重複的數字)
- 再找下一個空白格找可能的數字
- 如果沒有可以填的數字,則回到上一格填寫的數字,填寫下一個可能的數字。
- 如果上一格已經沒有可以填寫的數字了,再回到上上格以此類推。如果有找到可以填寫的數字,則從第 2 步驟繼續往下。
- 直到所有空白格都填上數字即完成。
實際程式我使用遞迴的方式,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| function solveSudoku(board) { recurse(board); return board }
function recurse(board) { for(let row = 0; row < 9; row++){ for(let col = 0; col < 9; col++){ if(board[row][col] === "."){
const possibles = Array.from({length: 9}, () => true)
for(let i=0; i<9; i++){ if(board[row][i] !== "."){ possibles[Number(board[row][i])-1] = false; } if(board[i][col] !== "."){ possibles[Number(board[i][col])-1] = false; } }
const blockStart = Math.floor(row/3) * 3; const blockEnd = Math.floor(col/3) * 3; for(let k=blockStart; k<blockStart+3; k++) { for(let l=blockEnd; l<blockEnd+3; l++) { if(board[k][l] !== "."){ possibles[Number(board[k][l])-1] = false; } } }
for(let m = 0; m<9; m++){ if(!possibles[m]) continue; board[row][col] = (m+1).toString();
if(recurse(board)){ return true; } else{ board[row][col] = "."; } } return false; } } } return true; }
|