[leetcode] 212. Word Search 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.

这道题是在字母表中找多个单词,题目难度为Hard。


题目和第79题(传送门)相关,第79题找一个单词,通过回溯法能够轻松解决题目,在处理79题时用了isUsed数组来标记每个位置是否已经遍历到,其实是没必要的。具体回溯法的思路就不解释了,相信大家都清楚。


这里要找多个单词,逐个通过回溯法查找效率肯定很低,就不考虑了。题目提示用字典树,解决起来就很方便了,第208题(传送门)是设计字典树的题目,不清楚字典树的同学可以先看下。遍历到某个位置时,之前遍历位置组成的字符串如果不是任何待查找字符串的前缀,就可以结束当前递归的分支了。是否是前缀可以通过遍历位置字典树节点指针是否为空来判断,如果为空,表明没有待查找字符串以此为前缀,结束分支,如果不为空可继续深度优先遍历。具体代码:

class TrieNode {
public:
    vector<TrieNode*> child;
    bool isIn;
    // Initialize your data structure here.
    TrieNode() : child(vector<TrieNode*>(26, NULL)), isIn(false) {}
};

class Trie {
public:
    Trie() : root(new TrieNode()) {}

    ~Trie() {
        delNode(root);
    }
    
    void delNode(TrieNode* n) {
        for(int i=0; i<26; ++i) {
            if(n->child[i]) delNode(n->child[i]);
        }
        delete n;
    }
    
    TrieNode* getRoot() {
        return root;
    }
    
    // Inserts a word into the trie.
    void insert(string word) {
        TrieNode* n = root;
        for(auto ch:word) {
            if(n->child[ch-'a'] == NULL) 
                n->child[ch-'a'] = new TrieNode();
            n = n->child[ch-'a'];
        }
        n->isIn = true;
    }

private:
    TrieNode* root;
};

class Solution {
    void chkExist(vector<vector<char>>& board, TrieNode* n, vector<string>& ret, string curStr, int r, int c) {
        n = n->child[board[r][c]-'a'];
        if(n) {
            curStr += board[r][c];
            if(n->isIn) {
                ret.push_back(curStr);
                n->isIn = false;
            }
            char ch = board[r][c];
            board[r][c] = 0;
            if(r > 0 && board[r-1][c]) 
                chkExist(board, n, ret, curStr, r-1, c);
            if(r < board.size()-1 && board[r+1][c]) 
                chkExist(board, n, ret, curStr, r+1, c);
            if(c > 0 && board[r][c-1]) 
                chkExist(board, n, ret, curStr, r, c-1);
            if(c < board[0].size()-1 && board[r][c+1]) 
                chkExist(board, n, ret, curStr, r, c+1);
            board[r][c] = ch;
        }
    }
public:
    vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
        vector<string> ret;
        int row = board.size();
        if(!row) return ret;
        int col = board[0].size();
        if(!col) return ret;
        
        Trie t;
        for(auto s:words) t.insert(s);
        
        for(int i=0; i<row; ++i) {
            for(int j=0; j<col; ++j) {
                chkExist(board, t.getRoot(), ret, "", i, j);
            }
        }
        
        return ret;
    }
};


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值