zoukankan      html  css  js  c++  java
  • [LeetCode] 212. Word Search II 词语搜索 II

    Given a 2D board and a list of words from the dictionary, find all words in the board.

    Each word must be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once in a word.

    For example,
    Given words = ["oath","pea","eat","rain"] and board =

    [
      ['o','a','a','n'],
      ['e','t','a','e'],
      ['i','h','k','r'],
      ['i','f','l','v']
    ]
    

    Return ["eat","oath"].

    Note:
    You may assume that all inputs are consist of lowercase letters a-z.

    Hint:

    You would need to optimize your backtracking to pass the larger test. Could you stop backtracking earlier?

    If the current candidate does not exist in all words' prefix, you could stop backtracking immediately. What kind of data structure could answer such query efficiently? Does a hash table work? Why or why not? How about a Trie? If you would like to learn how to implement a basic trie, please work on this problem: Implement Trie (Prefix Tree) first.

    79. Word Search 的拓展,79题是给一个单词让判断是否存在,现在是给了一堆单词,让返回所有存在的单词。

    解法:还是用79题的DFS方法,数据结构用字典树Trie

    有关字典树的题还有:208. Implement Trie (Prefix Tree) ,  211. Add and Search Word - Data structure design

    Java:

    public List<String> findWords(char[][] board, String[] words) {
        List<String> res = new ArrayList<>();
        TrieNode root = buildTrie(words);
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[0].length; j++) {
                dfs (board, i, j, root, res);
            }
        }
        return res;
    }
    
    public void dfs(char[][] board, int i, int j, TrieNode p, List<String> res) {
        char c = board[i][j];
        if (c == '#' || p.next[c - 'a'] == null) return;
        p = p.next[c - 'a'];
        if (p.word != null) {   // found one
            res.add(p.word);
            p.word = null;     // de-duplicate
        }
    
        board[i][j] = '#';
        if (i > 0) dfs(board, i - 1, j ,p, res); 
        if (j > 0) dfs(board, i, j - 1, p, res);
        if (i < board.length - 1) dfs(board, i + 1, j, p, res); 
        if (j < board[0].length - 1) dfs(board, i, j + 1, p, res); 
        board[i][j] = c;
    }
    
    public TrieNode buildTrie(String[] words) {
        TrieNode root = new TrieNode();
        for (String w : words) {
            TrieNode p = root;
            for (char c : w.toCharArray()) {
                int i = c - 'a';
                if (p.next[i] == null) p.next[i] = new TrieNode();
                p = p.next[i];
           }
           p.word = w;
        }
        return root;
    }
    
    class TrieNode {
        TrieNode[] next = new TrieNode[26];
        String word;
    }  

    Python:

    class TrieNode(object):
        # Initialize your data structure here.
        def __init__(self):
            self.is_string = False
            self.leaves = {}
    
        # Inserts a word into the trie.
        def insert(self, word):
            cur = self
            for c in word:
                if not c in cur.leaves:
                    cur.leaves[c] = TrieNode()
                cur = cur.leaves[c]
            cur.is_string = True
    
    
    class Solution(object):
        def findWords(self, board, words):
            """
            :type board: List[List[str]]
            :type words: List[str]
            :rtype: List[str]
            """
            visited = [[False for j in xrange(len(board[0]))] for i in xrange(len(board))]
            result = {}
            trie = TrieNode()
            for word in words:
                trie.insert(word)
                
            for i in xrange(len(board)):
                for j in xrange(len(board[0])):
                    if self.findWordsRecu(board, trie, 0, i, j, visited, [], result):
                        return True
            
            return result.keys()
        
        def findWordsRecu(self, board, trie, cur, i, j, visited, cur_word, result):
            if not trie or i < 0 or i >= len(board) or j < 0 or j >= len(board[0]) or visited[i][j]:
                return
            
            if board[i][j] not in trie.leaves:
                return
            
            cur_word.append(board[i][j])
            next_node = trie.leaves[board[i][j]]
            if next_node.is_string:
                result["".join(cur_word)] = True
            
            visited[i][j] = True
            self.findWordsRecu(board, next_node, cur + 1, i + 1, j, visited, cur_word, result)
            self.findWordsRecu(board, next_node, cur + 1, i - 1, j, visited, cur_word, result)
            self.findWordsRecu(board, next_node, cur + 1, i, j + 1, visited, cur_word, result)
            self.findWordsRecu(board, next_node, cur + 1, i, j - 1, visited, cur_word, result)     
            visited[i][j] = False
            cur_word.pop() 

    C++:

    class Solution {
    public:
        struct TrieNode {
            TrieNode *child[26];
            string str;
            TrieNode() : str("") {
                for (auto &a : child) a = NULL;
            }
        };
        struct Trie {
            TrieNode *root;
            Trie() : root(new TrieNode()) {}
            void insert(string s) {
                TrieNode *p = root;
                for (auto &a : s) {
                    int i = a - 'a';
                    if (!p->child[i]) p->child[i] = new TrieNode();
                    p = p->child[i];
                }
                p->str = s;
            }
        };
        vector<string> findWords(vector<vector<char> >& board, vector<string>& words) {
            vector<string> res;
            if (words.empty() || board.empty() || board[0].empty()) return res;
            vector<vector<bool> > visit(board.size(), vector<bool>(board[0].size(), false));
            Trie T;
            for (auto &a : words) T.insert(a);
            for (int i = 0; i < board.size(); ++i) {
                for (int j = 0; j < board[i].size(); ++j) {
                    if (T.root->child[board[i][j] - 'a']) {
                        search(board, T.root->child[board[i][j] - 'a'], i, j, visit, res);
                    }
                }
            }
            return res;
        }
        void search(vector<vector<char> > &board, TrieNode *p, int i, int j, vector<vector<bool> > &visit, vector<string> &res) { 
            if (!p->str.empty()) {
                res.push_back(p->str);
                p->str.clear();
            }
            int d[][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
            visit[i][j] = true;
            for (auto &a : d) {
                int nx = a[0] + i, ny = a[1] + j;
                if (nx >= 0 && nx < board.size() && ny >= 0 && ny < board[0].size() && !visit[nx][ny] && p->child[board[nx][ny] - 'a']) {
                    search(board, p->child[board[nx][ny] - 'a'], nx, ny, visit, res);
                }
            }
            visit[i][j] = false;
        }
    };
    

    类似题目:

    [LeetCode] 79. Word Search 单词搜索

    [LeetCode] 208. Implement Trie (Prefix Tree) 实现字典树(前缀树)

      

    All LeetCode Questions List 题目汇总

  • 相关阅读:
    web前端学习笔记(CSS盒子的定位)
    web前端学习笔记(CSS盒子的浮动)
    数百篇「原创」文章,助你完成技术「体系化」
    linux quota磁盘限额,引发的rename系统调用 errno:18
    dnsperf
    stop容器,把信号量传给java进程,优雅退出
    JNA 调用操作系统函数 和 系统调用
    自顶向下深入分析Netty(五)--Future
    来测试下你的Java编程能力
    Netty笔记
  • 原文地址:https://www.cnblogs.com/lightwindy/p/8614971.html
Copyright © 2011-2022 走看看