• 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;
            }
        }
    };
  • 相关阅读:
    python的模块future用法实例解析
    strcmp函数和memcmp函数的用法区别及联系
    esp8266 smartconfig-智能配网分析和使用及注意事项
    ubuntu 18.04 安装并配置adb
    Markdown的常用方法总结
    mac下使用minicom几个注意事项
    最强Linux shell工具Oh My Zsh 指南
    ESP8266源码分析--打印的基本用法
    atom 在Ubuntu 18.04 上安装及基本使用
    ubuntu 查看端口被占用并删除端口
  • 原文地址:https://www.cnblogs.com/heyn1/p/11051413.html
Copyright © 2020-2023  润新知