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.

 

题目大意

给定一个二维数组,数组中包含小写字母,同时给一个字符串数组,数组中每个字符串为一个单词,要求查找出在字符串数组中出现的,并且能在二维数组拼接出来的单词(在二维数组中,当两个字母上下左右拼接在一起时可以组成一个单词的序列)。

 

示例

E

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

Output: ["eat","oath"]

 

解题思路

根据LeetCode@rabeeh的思路,需要建立一个Trie结构的树(Trie结构如题LeetCode - 211所述),即该树保存了字符串数组中所有单词的前缀表示。并遍历二维数组中的每一个位置,在每个位置开始进行树节点查找,查找符合条件的单词并加入结果集合中。

 

复杂度分析

时间复杂度:O(|V| + |E|)

空间复杂度:O(|V| + |E|)

 

代码

//树结点结构
class TrieNode {
public:
    bool end;
    vector<TrieNode*> children;
    
    TrieNode() {
        end = false;
        children = vector<TrieNode*>(26, NULL);
    }
};

class Trie {
public:
    //树的初始化,为每个单词建立一个树的从根节点到叶节点的路径
    Trie(vector<string>& words) {
        root = new TrieNode();
        for(string word : words) {
            addNode(word);
        }
    }
    
    TrieNode* getRoot() {
        return root;
    }
    
    void addNode(string word) {
        TrieNode* cur = root;
        for(int i = 0; i < word.length(); ++i) {
            if(!cur->children[word[i] - 'a']) {
                cur->children[word[i] - 'a'] = new TrieNode();
            }
            cur = cur->children[word[i] - 'a'];
        }
        cur->end = true;
    }
    
private:
    TrieNode* root;
};

class Solution {
public:
    vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
        Trie* tree = new Trie(words);
        TrieNode* root = tree->getRoot();
        unordered_set<string> res;
        //以二维数组中的当前位置为单词的起始字母进行查找
        for(int i = 0; i < board.size(); ++i) {
            for(int j = 0; j < board[0].size(); ++j) {
                find(board, root, res, i, j, "");
            }
        }
        
        vector<string> ans;
        for(auto iter = res.begin(); iter != res.end(); ++iter)
            ans.push_back(*iter);
        
        return ans;
    }
    
    void find(vector<vector<char> >& board, TrieNode* node, unordered_set<string>& res, int x, int y, string word) {
        //若访问位置越界或该位置已被访问则返回
        if(x < 0 || x >= board.size() || y < 0 || y >= board[0].size() || board[x][y] == ' ')
            return;
        
        if(node->children[board[x][y] - 'a'] != NULL) {
            char c = board[x][y];
            word += c;
            board[x][y] = ' ';
            //若当前节点是某个单词的结尾,则代表可以找到一个符合条件的单词
            if(node->children[c - 'a']->end)
                res.insert(word);
            //依次查找二维数组的四个方向,进行递归遍历
            find(board, node->children[c - 'a'], res, x - 1, y, word);
            find(board, node->children[c - 'a'], res, x, y + 1, word);
            find(board, node->children[c - 'a'], res, x + 1, y, word);
            find(board, node->children[c - 'a'], res, x, y - 1, word);
            board[x][y] = c;
        }
    }
};

 

转载于:https://www.cnblogs.com/heyn1/p/11051413.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值