212. word-search-ii

37 篇文章 0 订阅
12 篇文章 0 订阅

       这道题乍一看基本的思路就是深度优先遍历,如果根据一个词,遍历一遍整个数据表,那复杂度显然是比较高的,每个词都要遍历一遍二维数组表,而且每个字母要做一次深度优先遍历,这种暴力寻找的做法空间没有浪费,但是时间复杂度太高,起初在做这道题的时候,也没有较好的解决办法。但是想到前面有一个题目字典树的做法,通过空间来换取时间上的高效,因此想到这里,就先对原先的字符串数组构建字典树。

       题目大意:给定一组字符串数组和一个二维字符数组表,查找二维数组表,而且每个字符串必须由顺序相邻的单元的字母构成,其中“相邻”单元是水平或垂直相邻的单元。 一个单词中不能多次使用相同的字母单元格。

      字典序解题思路:

       <1>、构建字典树,即将所有字符串拆开用字典树存储起来。

       <2>、循环遍历整个二维字符数组,每次采用深度优先遍历,每一次可以将相同开头的字母全部找到。

以下是AC的代码:

struct TrieNode {
    vector<TrieNode*> trienodes;
    string str;
    TrieNode() {
        for (int i=0; i<26; ++i) {
            trienodes.push_back(NULL);
        }
        str = "";
    }
};

class Trie {
public:
    TrieNode* tireroot = new TrieNode();

    void insert(string str) {
        TrieNode *tmp = tireroot;
        for (int i=0; i<str.size(); ++i) {
            if (tmp->trienodes[str[i]-'a'] == NULL) {
                tmp->trienodes[str[i]-'a'] = new TrieNode();
            }
            tmp = tmp->trienodes[str[i]-'a'];
        }
        tmp->str = str;
    }
};

class Solution {
public:
    vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
        if (board.empty() || board[0].size()<1 || words.size()<1) {
            return res;
        }
        vector<vector<bool>> visit(board.size(), vector<bool>(board[0].size(), 0));
        Trie T;
        for (string str : words) {
            T.insert(str);
        }
        for (int i=0; i<board.size(); ++i) {
            for (int j=0; j<board[i].size(); ++j) {
                if (T.tireroot->trienodes[board[i][j]-'a']) {
                    findWords(board, visit, T.tireroot->trienodes[board[i][j]-'a'] , i, j);
                }
            }
        }
        return res;
    }

    void findWords(vector<vector<char>>& board, vector<vector<bool>>&visit, TrieNode* p, int x, int y) {
        if (p->str.size() >= 1) {
            res.push_back(p->str);
            p->str = "";
        }
        visit[x][y] = 1;
        vector<vector<int>> direct = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
        for (int i=0; i<direct.size(); ++i) {
            int nx = x+direct[i][0], ny = y+direct[i][1];
            if (nx>=0&&nx<board.size() && ny>=0&&ny<board[0].size() && !visit[nx][ny] && p->trienodes[board[nx][ny]-'a']) {
                findWords(board, visit, p->trienodes[board[nx][ny]-'a'], nx, ny);
            }
        }
        visit[x][y] = 0;
    }

private:
    vector<string> res;
};

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值