單詞搜索 II (LeetCode第212題)java實現

一、題目描述

給定一個二維網格 board 和一個字典中的單詞列表 words,找出所有同時在二維網格和字典中出現的單詞。

單詞必須按照字母順序,通過相鄰的單元格內的字母構成,其中“相鄰”單元格是那些水平相鄰或垂直相鄰的單元格。同一個單元格內的字母在一個單詞中不允許被重複使用。

示例:

輸入: 
words = ["oath","pea","eat","rain"] and board =
[
  ['o','a','a','n'],
  ['e','t','a','e'],
  ['i','h','k','r'],
  ['i','f','l','v']
]

輸出: ["eat","oath"]
說明:
你可以假設所有輸入都由小寫字母 a-z 組成。

提示:

你需要優化回溯算法以通過更大數據量的測試。你能否早點停止回溯?
如果當前單詞不存在於所有單詞的前綴中,則可以立即停止回溯。什麼樣的數據結構可以有效地執行這樣的操作?散列表是否可行?爲什麼? 前綴樹如何?如果你想學習如何實現一個基本的前綴樹,請先查看這個問題: 實現Trie(前綴樹)。

二、解題思路

這是一道hard題,原因是考察了:字典樹 和 回溯法+動態規劃。

具體思路就是先實現字典樹的數據結構,再用回溯求出結果。

三、可運行java代碼

​
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

public class findWords_212 {
    public List<String> findWords(char[][] board, String[] words) {
        //構建字典樹
        wordTrie myTrie=new wordTrie();
        trieNode root=myTrie.root;
        for(String s:words)
            myTrie.insert(s);

        //使用set防止重複
        Set<String> result =new HashSet<>();
        int m=board.length;
        int n=board[0].length;
        boolean [][]visited=new boolean[m][n];
        //遍歷整個二維數組
        for(int i=0;i<board.length; i++){
            for (int j = 0; j < board [0].length; j++){
                find(board,visited,i,j,m,n,result,root);
            }
        }
        System.out.print(result);
        return new LinkedList<String>(result);
    }
    private void find(char [] [] board, boolean [][]visited,int i,int j,int m,int n,Set<String> result,trieNode cur){
        //邊界以及是否已經訪問判斷
        if(i<0||i>=m||j<0||j>=n||visited[i][j])
            return;
        cur=cur.child[board[i][j]-'a'];
        visited[i][j]=true;
        if(cur==null)
        {
            //如果單詞不匹配,回退
            visited[i][j]=false;
            return;
        }
        //找到單詞加入
        if(cur.isLeaf)
        {
            result.add(cur.val);
            //找到單詞後不能回退,因爲可能是“ad” “addd”這樣的單詞得繼續回溯
//            visited[i][j]=false;
//            return;
        }
        find(board,visited,i+1,j,m,n,result,cur);
        find(board,visited,i,j+1,m,n,result,cur);
        find(board,visited,i,j-1,m,n,result,cur);
        find(board,visited,i-1,j,m,n,result,cur);
        //最後要回退,因爲下一個起點可能會用到上一個起點的字符
        visited[i][j]=false;
    }


}

//字典樹
class wordTrie{
    public trieNode root=new trieNode();
    public void insert(String s){
        trieNode cur=root;
        for(char c:s.toCharArray()){
            if(cur.child[c-'a']==null){
                cur.child [c-'a'] = new trieNode();
                cur=cur.child[c-'a'];
            }else
                cur=cur.child [c-'a'];
        }
        cur.isLeaf=true;
        cur.val=s;
    }
}
//字典樹結點
class trieNode{
    public String val;
    public trieNode[] child=new trieNode[26];
    public boolean isLeaf=false;

    trieNode(){

    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章