Java實現 LeetCode 212 單詞搜索 II(二)

212. 單詞搜索 II

給定一個二維網格 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(前綴樹)。

PS:
首先構建一個字典樹,然後在dfs的時候加入字典樹,以某個字符串結尾的可以減少搜索次數
這裏爲什麼不用開頭用結尾呢, (●ˇ∀ˇ●)
結尾在這裏就是我搜索完一個,我可以直接比較,如果沒有的話,我再返回上一個,

class TrieNode {
    private static final int ALPHABET_SIZE = 26;

    TrieNode[] children = new TrieNode[ALPHABET_SIZE];
    // 判斷這個前綴是不是某個字符串的結尾
    boolean isEndOfWord = false;
    TrieNode() {
        isEndOfWord = false;
        for (int i = 0; i < ALPHABET_SIZE; i++)
            children[i] = null;
    }
}

class Trie {
    public TrieNode root;
    /** Initialize your data structure here. */
    public Trie() {
        root = new TrieNode();
    }
    /** Inserts a word into the trie. */
    public void insert(String word) {
        TrieNode curNode = root;
        int index;
        for (int i = 0; i < word.length(); i++) {
            index = word.charAt(i) - 'a';
            if (curNode.children[index] == null) {
                curNode.children[index] = new TrieNode();
            }
            curNode = curNode.children[index];
        }
        curNode.isEndOfWord = true;
    }
}
class Solution {
    public List<String> findWords(char[][] board, String[] words) {
        List<String> result = new ArrayList<>();
        if (words == null || words.length == 0 || board == null || board.length == 0 || board[0].length == 0)
            return result;

        Trie trie = new Trie();
        for (String temp : words)
            trie.insert(temp);

        TrieNode root = trie.root;
        boolean[][] visited = new boolean[board.length][board[0].length];
        Set<String> tempResult = new HashSet<>();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[0].length; j++) {
                if (root.children[board[i][j] - 'a'] != null ) {
                    dfs(board, visited, i, j, root.children[board[i][j] - 'a'], tempResult, sb);
                }
            }
        }

        // 需要把tempResult這個set拷貝到真正的result List中進行返回
        Iterator<String> iterator = tempResult.iterator();
        while (iterator.hasNext()) {
            result.add(iterator.next());
        }
        return result;
    }

    private void dfs(char[][] board, boolean[][] visited, int startIInBoard, int startJInBoard
            , TrieNode curNode, Set<String> resultSet, StringBuilder curStrBuilder) {
        curStrBuilder.append(board[startIInBoard][startJInBoard]);
        visited[startIInBoard][startJInBoard] = true;
        if (curNode.isEndOfWord) {
            resultSet.add(curStrBuilder.toString());
        }
        // 向上搜索, 如果上面的格子沒有被搜索過的話
        if (startIInBoard > 0 && !visited[startIInBoard - 1][startJInBoard]
                && curNode.children[board[startIInBoard - 1][startJInBoard] - 'a'] != null) {
            dfs(board, visited,startIInBoard - 1, startJInBoard
                    , curNode.children[board[startIInBoard - 1][startJInBoard] - 'a'], resultSet, curStrBuilder);
        }
        // 向下搜索
        if (startIInBoard < board.length - 1 && !visited[startIInBoard + 1][startJInBoard]
                && curNode.children[board[startIInBoard + 1][startJInBoard] - 'a'] != null) {
            dfs(board, visited,startIInBoard + 1, startJInBoard
                    , curNode.children[board[startIInBoard + 1][startJInBoard] - 'a'], resultSet, curStrBuilder);
        }
        // 向左搜索
        if (startJInBoard > 0 && !visited[startIInBoard][startJInBoard - 1]
                && curNode.children[board[startIInBoard][startJInBoard - 1] - 'a'] != null) {
            dfs(board, visited, startIInBoard, startJInBoard - 1
                    , curNode.children[board[startIInBoard][startJInBoard - 1] - 'a'], resultSet, curStrBuilder);
        }
        // 向右搜索
        if (startJInBoard < board[0].length - 1 && !visited[startIInBoard][startJInBoard + 1]
                && curNode.children[board[startIInBoard][startJInBoard + 1] - 'a'] != null) {
            dfs(board, visited, startIInBoard, startJInBoard + 1
                    , curNode.children[board[startIInBoard][startJInBoard + 1] - 'a'], resultSet, curStrBuilder);
        }
        // 恢復現場
        curStrBuilder.setLength(curStrBuilder.length() - 1);
        visited[startIInBoard][startJInBoard] = false;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章