【leetcode】 37. 解數獨

一 、運用 回溯法 解數獨

  • 回溯法算法思想:(參考 回溯法

定義:

回溯法(探索與回溯法)是一種選優搜索法,按選優條件向前搜索,以達到目標。但當探索到某一步時,發現原先選擇並不優或達不到目標,就退回一步重新選擇,這種走不通就退回再走的技術爲回溯法,而滿足回溯條件的某個狀態的點稱爲“回溯點”。

1、回溯法適用:有許多問題,當需要找出它的解集(全部解)或者要求回答什麼解是滿足某些約束條件的最優解時,往往要使用回溯法。

2、有組織的窮舉式搜索:回溯法的基本做法是搜索或者有的組織窮盡搜索。它能避免搜索所有的可能性。即避免不必要的搜索。這種方法適用於解一些組合數相當大的問題。

3、搜索解空間樹:回溯法在問題的解空間樹中,按深度優先策略,從根結點出發搜索解空間樹。算法搜索至解空間樹的任意一點時,先判斷該結點是否包含問題的解。如果肯定不包含(剪枝過程),則跳過對該結點爲根的子樹的搜索,逐層向其祖先結點回溯;否則,進入該子樹,繼續按深度優先策略搜索。

在這裏插入圖片描述
找到子數獨法

let boxRow = (parseInt(row/3)*3)+parseInt(i/3); //子數獨行標
let boxCol = (parseInt(col/3)*3)+i%3;//子數獨列標

算法

  • 行循環,嵌套列循環
  • 找到沒有數字的數組
 if (board[i][j] == '.')  {}
  • 開始嘗試填寫數字1-9,isValid 檢驗填充數字是否有重複。有重複就回溯重新開始
 for(let num = 1; num<10; num++) {
     //檢驗填充數字的正確性

      if (isValid(i,j,num)) {
          board[i][j] = String(num);
          //遞歸
          if (solve(board)) {
              return true;
          }
          board[i][j] = '.';

      }
  }
 

    let isValid = (row,col,num) => {
        
        //定位到每個小格子的座標
        for (let i = 0; i < 9; i++) {
            let boxRow = (parseInt(row/3)*3)+parseInt(i/3); //子數獨行標
            let boxCol = (parseInt(col/3)*3)+i%3;//子數獨列標
            //console.log(boxRow + '_' + boxCol); 
            
            if (board[row][i] == num || board[i][col] == num || board[boxRow][boxCol] == num) {
                return false;
            }
        }
    
        return true;

     
    }

完整代碼 js

   var sd = new solveSudoku([
    ["5", "3", ".", ".", "7", ".", ".", ".", "."],
    ["6", ".", ".", "1", "9", "5", ".", ".", "."],
    [".", "9", "8", ".", ".", ".", ".", "6", "."],
    ["8", ".", ".", ".", "6", ".", ".", ".", "3"],
    ["4", ".", ".", "8", ".", "3", ".", ".", "1"],
    ["7", ".", ".", ".", "2", ".", ".", ".", "6"],
    [".", "6", ".", ".", ".", ".", "2", "8", "."],
    [".", ".", ".", "4", "1", "9", ".", ".", "5"],
    [".", ".", ".", ".", "8", ".", ".", "7", "9"]
]);

/**
 * @param {character[][]} board
 * @return {void} Do not return anything, modify board in-place instead.
 */
var solveSudoku = function (board) {
    
    //檢驗填充數字的正確性 row 行 col列 num 填充數字
    
    let isValid = (row,col,num) => {
        
        //循環嘗試填充數字 
        for (let i = 0; i < 9; i++) {
            let boxRow = (parseInt(row/3)*3)+parseInt(i/3); //子數獨行標
            let boxCol = (parseInt(col/3)*3)+i%3;//子數獨列標
            //console.log(boxRow + '_' + boxCol); 
          
            if (board[row][i] == num || board[i][col] == num || board[boxRow][boxCol] == num) {
                return false;
            }
        }
    
        return true;

     
    }
    //聲明一個塊級變量
    let solve =() => {
        //循環行
        for (let i = 0; i < 9; i++) {
            //循環列
            for (let j = 0; j < 9; j++) {
               //判斷填充資格
               if (board[i][j] == '.') {
                    //開始循環數字
                    for(let num = 1; num<10; num++) {
                        //檢驗填充數字的正確性

                        if (isValid(i,j,num)) {
                            board[i][j] = String(num);
                            //遞歸
                            if (solve(board)) {
                                return true;
                            }
                            board[i][j] = '.';

                        }
                    }
                    return false;
                    
               }
            }
        }
        return true;
        
    }

    solve(board);
    console.log(board);
    return board;
};

發佈了78 篇原創文章 · 獲贊 34 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章