Leetcode (212) Word Search II

来源:互联网 发布:淘宝推广认准晨昊网络 编辑:程序博客网 时间:2024/05/16 00:30
  • 题目:

    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”].

  • 题意:给定一些单词,要求在一个board上面找到所有在单词表中的单词。

  • 思路:找单词,基本就是枚举每一个位置作为起点,从起点出发,进行深度优先搜索,找到所有单词,但是这样子的时间复杂度将是指数级的,需要进行剪枝。剪枝的思路也很简单,因为暴力枚举的时候,如在example里面,可能会有”athflv”,但是实际上单词表中并没有以a开头的单词,因此以a开头的所有搜索都是不必要的,从而达到剪枝的效果。而具体操作可以为单词表建立一颗字典树,用于剪枝和检查单词在不在单词表中。字典复杂度为O(m),m为字典中单词最长长度。所以总的时间复杂度远不及O(n3m),即一个很松的上界。

  • 代码:

class Solution {public:    vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {        root = new TrieNode();        vector<string> ans;        for (auto word: words)        {            insert(word);        }        int rows=board.size();        if (rows == 0) return ans;        int cols=board[0].size();        for (int i=0;i<rows;++i)        {            for (int j=0;j<cols;++j)            {                if (root->next[board[i][j]-'a'])                {                    string word=string(1, board[i][j]);                    if (isWord(word)) ans.push_back(word);                    vis[i][j]=true;                    dfs(i, j, board, ans, word);                    vis[i][j]=false;                }            }        }        sort(ans.begin(), ans.end());        auto last = unique(ans.begin(), ans.end());        return vector<string>(ans.begin(), last);    }private:    static const int dir[][2];    bool vis[100][100];    void dfs(int x, int y, const vector<vector<char>>& board, vector<string>& ans, const string& word)    {        int rows=board.size(), cols=board[0].size();        for (int i=0;i<4;++i)        {            int nx=x+dir[i][0], ny=y+dir[i][1];            if (nx<0 || ny<0 || nx>=rows || ny>=cols || vis[nx][ny]) continue;            string newWord = word+board[nx][ny];            if (hasPath(newWord))            {                if (isWord(newWord))                {                    ans.push_back(newWord);                }                vis[nx][ny]=true;                dfs(nx, ny, board, ans, newWord);                vis[nx][ny]=false;            }        }    }    struct TrieNode     {        bool isEnd;        TrieNode* next[26];        TrieNode(bool is=false)        {            isEnd = is;            memset(next, 0, sizeof(next));        }    };    TrieNode* root;    void free(TrieNode* node)    {        if (!node) return;        for (int i=0;i<26;++i)        {            free(node->next[i]);        }    }    void insert(const string& word)    {        TrieNode* node=root;        for (int i=0;i<word.length();++i)        {            int idx = word[i]-'a';            if (!node->next[idx])            {                node->next[idx] = new TrieNode();            }            node = node->next[idx];            if (i == word.length()-1) node->isEnd=true;        }    }    bool hasPath(const string& word)    {        TrieNode* node=root;        for (int i=0;i<word.length();++i)        {            int idx = word[i]-'a';            if (node->next[idx])            {                node = node->next[idx];            }            else            {                return false;            }        }        return true;    }    bool isWord(const string& word)    {        TrieNode* node=root;        for (int i=0;i<word.length();++i)        {            int idx = word[i]-'a';            if (node->next[idx])            {                node = node->next[idx];            }            else            {                return false;            }        }        return node->isEnd;    }};const int Solution::dir[][2] ={1,0,0,1,-1,0,0,-1};
0 0