LeetCode: 212. 单词搜索II

116 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第10天,点击查看活动详情

212. 单词搜索II

来源:力扣(LeetCode)

链接: leetcode.cn/problems/wo…

给定一个 m x n 二维字符网格 board和一个单词(字符串)列表 words, 返回所有二维网格上的单词 。

单词必须按照字母顺序,通过 相邻的单元格 内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。

示例 1: 在这里插入图片描述

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

示例 2:

输入:board = [["a","b"],["c","d"]], words = ["abcb"]
输出:[]

提示:

  • m == board.length
  • n == board[i].length
  • 1 <= m, n <= 12
  • board[i][j] 是一个小写英文字母
  • 1 <= words.length <= 31043 * 10^4
  • 1 <= words[i].length <= 10
  • words[i] 由小写英文字母组成
  • words 中的所有字符串互不相同

解法

  • 字典树+DFS:
    • 首先对words使用字典树进行保存,方便后续的查找
    • 之后对每个格子进行dfs搜索,看看每个格子位置的字符是否在字典树中,如果在的话先确定是否能成为单词,如果不是单词继续朝着四个方向遍历下去,这里注意同一个单元格内字母不能重复使用,因此遍历每个字符时候先改变其状态,遍历完成之后重置为原来的字符;

代码实现

字典树+DFS

python实现

class Solution:
    def findWords(self, board: List[List[str]], words: List[str]) -> List[str]:
        tries = dict()
        for word in words:
            t = tries
            for ch in word:
                if ch not in t:
                    t[ch] = dict()
                t = t[ch]
            t['end'] = 1

        res = []
        m = len(board)
        n = len(board[0])
        def dfs(i, j, s, tries):
            ch = board[i][j]
            if ch not in tries:
                return
            tries = tries[ch]
            if 'end' in tries and tries['end'] == 1:
                res.append(s+ch)
                tries['end'] = 0
            board[i][j] = '#'
            for dx, dy in [(0, 1), (0, -1), (-1, 0), (1, 0)]:
                ni = i + dx
                nj = j + dy
                if 0 <= ni < m and 0 <= nj < n and board[ni][nj] != '#':
                    dfs(ni, nj, s+ch, tries)
            board[i][j] = ch

        for i in range(m):
            for j in range(n):
                dfs(i, j, '', tries)
        return res

c++实现

struct Trie {
    Trie* children[26] = {nullptr};
    string word = "";
};

class Solution {
private:
        vector<string> ans;
        vector<int> dir = {-1, 0, 1, 0, -1};
        Trie* initializeTree(vector<string>& words) {
            Trie* t = new Trie();
            Trie* cur;
            for (auto word: words) {
                cur = t;
                for (auto ch: word) {
                    if (cur->children[ch-'a'] == nullptr)
                        cur->children[ch-'a'] = new Trie();
                    cur = cur->children[ch-'a'];
                }
                cur->word = word;
            }
            return t;
        }

        void dfs(vector<vector<char>>& board, Trie* t, int i, int j) {
            char tmp = board[i][j];
            if (tmp == '*' || t->children[tmp-'a'] == nullptr) return ;
            t = t->children[tmp-'a'];
            if (t->word != ""){
                ans.emplace_back(t->word);
                t->word = "";
            }
            board[i][j] = '*';
            for (int k=0; k<4; k++) {
                int r = i+dir[k], c = j+dir[k+1];
                if (r >= 0 && r < board.size() && c >= 0 && c < board[0].size())
                    dfs(board, t, r, c);
            }
            board[i][j] = tmp;
            return ;
        }

public:
    vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
        Trie* t = initializeTree(words);
        for (int i=0; i<board.size(); i++) {
            for(int j=0; j<board[0].size(); j++) {
                dfs(board, t, i, j);
            }
        }
        return ans;
    }
};

复杂度分析

  • 时间复杂度: mnwordsm*n*words
  • 空间复杂度: mnwordsm*n*words
  • 时间空间复杂度存疑

参考