1. 程式人生 > >79. Word Search/212. Word Search II--圖的back tracking -- tier tree 待續

79. Word Search/212. Word Search II--圖的back tracking -- tier tree 待續

79題,

給你一個二維的board, 只能往上下左右四個方向走,為你是否能找到單詞。

board =
[
  ['A','B','C','E'],
  ['S','F','C','S'],
  ['A','D','E','E']
]

Given word = "ABCCED", return true.
Given word = "SEE", return true.
Given word = "ABCB", return false.

分析: 演算法並不難,從每個(i,j)為起點進行dfs, dfs 過程往上下左右四個方向走, 但不能走重複的節點,因此需要設定visted 來標記是否走過。
key point: 用visted 標記後,每次dfs 完後, 記得 visted 需要改成原來的value, 所謂的back tracking 就是體現在這裡。


程式被我一開始寫的太渣了:


class Solution {
    public boolean exist(char[][] board, String word) {
        
        int row = board[0].length;
        int col = board.length;
        
        
         boolean[][] visted = new boolean[col][row];
        for(int i=0; i<col; i++){
            for(int j=0; j<row; j++){
               
// System.out.println("start: "+ i+ " "+ j); if(dfs(i,j,board,visted,word,0)) return true; visted[i][j] = false; } } return false; } private boolean dfs(int i, int j, char[][] board, boolean[][] visted, String word, int
depth){ if(board[i][j] != word.charAt(depth)) return false; if(depth == word.length()-1){ return true; } boolean flag = false; visted[i][j] = true; //System.out.println(i+ " "+ j); //System.out.println(depth); //up if(i-1>=0&& !visted[i-1][j]){ flag = flag || dfs(i-1,j,board,visted,word,depth+1); visted[i-1][j] = false; if(flag) return true; } //down if(i+1<board.length &&!visted[i+1][j]) { flag = flag || dfs(i+1,j,board,visted,word,depth+1); visted[i+1][j] = false; if(flag) return true; } //left if(j-1 >=0 && !visted[i][j-1]){ flag = flag || dfs(i,j-1,board,visted,word,depth+1); visted[i][j-1] = false; if(flag) return true; } //right if(j+1<board[0].length&& !visted[i][j+1]){ flag = flag || dfs(i,j+1,board,visted,word,depth+1); visted[i][j+1] = false; if(flag) return true; } return flag; } }

 

又改成了:

class Solution {
    public boolean exist(char[][] board, String word) {
        
        int row = board[0].length;
        int col = board.length;
        
        
         boolean[][] visted = new boolean[col][row];
        for(int i=0; i<col; i++){
            for(int j=0; j<row; j++){
               // System.out.println("start: "+ i+ " "+ j);
               
                if(dfs(i,j,board,visted,word,0)) return true;
               // visted[i][j] = false;
            }
        }
        return false;
           
    }
    
    private boolean dfs(int i, int j, char[][] board, boolean[][] visted, String word, int depth){

                

        if(board[i][j] != word.charAt(depth)) return false;

        if(depth == word.length()-1){
            return true;
        }
        
        boolean flag = false;
        
        visted[i][j] = true;
        //System.out.println(i+ " "+ j);
        //System.out.println(depth);
      
        
        //up
        if(i-1>=0&& !visted[i-1][j]){
            flag = flag || dfs(i-1,j,board,visted,word,depth+1);
           // visted[i-1][j] = false;
            
            
        }
        //down
        if(i+1<board.length &&!visted[i+1][j]) {
            flag = flag || dfs(i+1,j,board,visted,word,depth+1);
           // visted[i+1][j] = false;
           
        }
        //left
        if(j-1 >=0 && !visted[i][j-1]){
            flag = flag || dfs(i,j-1,board,visted,word,depth+1);
          //  visted[i][j-1] = false;
           
        }
        //right    
        if(j+1<board[0].length&& !visted[i][j+1]){
           flag = flag ||  dfs(i,j+1,board,visted,word,depth+1);
          // visted[i][j+1] = false;
          
        }
        visted[i][j] = false;
        return flag;
    }
}

 

之所以寫的不好,主要因為,應該把 邊界條件和是否已經被訪問 判斷放在 下一次函式呼叫裡,而不是本次裡, 修改後的程式簡單很多。

back traking 體現在 visted[i][j] = true ; dfs(...) ; visted[i][j] = false;

class Solution {
    public boolean exist(char[][] board, String word) {
        
        int row = board[0].length;
        int col = board.length;
        
        
         boolean[][] visted = new boolean[col][row];
        for(int i=0; i<col; i++){
            for(int j=0; j<row; j++){    
                if(dfs(i,j,board,visted,word,0)) return true;
               
            }
        }
        return false;
           
    }
    
    private boolean dfs(int i, int j, char[][] board, boolean[][] visted, String word, int depth){

                
        if(i<0 || j<0 || i >=board.length || j>=board[0].length ) return false; 
        
        if(board[i][j] != word.charAt(depth)) return false;
        
        if(visted[i][j]) return false;

        if(depth == word.length()-1){
            return true;
        }
        
        
        
         visted[i][j] = true;
         boolean flag =   dfs(i-1,j,board,visted,word,depth+1) ||dfs(i+1,j,board,visted,word,depth+1) 
                       || dfs(i,j-1,board,visted,word,depth+1)|| dfs(i,j+1,board,visted,word,depth+1);
 
         visted[i][j] = false;
         return flag;
    }
}

 

212. Word Search II
和79 基本雷同,給你 一個 string[] words, 要你找出 words 符合 79題搜尋條件的單詞。
如果用 dfs, 在 79題基礎上加個for 迴圈就好了。
但有個坑爹的地方: 字典: ["a"] words = ["a","a"] ,只能回 "a" ,而不能回 "a","a" 因此需要用set 存放結果。

更好的做法是用tier tree, 待續。