Hard-题目48:212. Word Search II

本文介绍了一个二维矩阵中寻找特定单词的算法实现,通过构建Trie树优化搜索过程,避免重复计算,提高查找效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目原文:
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”].
Note:
You may assume that all inputs are consist of lowercase letters a-z.
题目大意:
给出一个由字母组成的二维矩阵,和一串单词,求哪些单词能用矩阵的一条路径表示。
题目分析:
本题是Middle-题目108:79. Word Search的延伸,如果简单的用一个for循环再调用第一题的函数,显然tle没商量。很容易想到是因为前缀相同的单词都进行了重复的搜索。那么针对相同前缀优化想到了什么?没错Trie树!
参考了discuss中一个最快的代码,大致意思是从矩阵的每一个点开始深搜,dfs的搜索路径和Trie树的搜索路径保持一致(即搜索到某一字符串时,当前dfs函数下的trie树节点也要对应一致),如果当前路径在trie树上是空节点,则直接退出;如果找到了一个Trie树节点它是单词,就加入答案并从Trie树上删掉这个单词。这样相同前缀的单词就只搜索了一次。
源码:(language:java)

public class Solution {
    public List<String> findWords(char[][] board, String[] words) {
        List<String> res = new ArrayList<>();
        TrieNode root = buildTrie(words);
        for(int i = 0; i < board.length; i++) {
            for(int j = 0; j < board[0].length; j++) {
                dfs(board, i, j, root, res);
            }
        }
        return res;
    }

    public void dfs(char[][] board, int i, int j, TrieNode p, List<String> res) {
        char c = board[i][j];
        if(c == '#' || p.next[c - 'a'] == null) return;
        p = p.next[c - 'a'];
        if(p.word != null) {   // found one
            res.add(p.word);
            p.word = null;     // de-duplicate
        }

        board[i][j] = '#';
        if(i > 0) dfs(board, i - 1, j ,p, res); 
        if(j > 0) dfs(board, i, j - 1, p, res);
        if(i < board.length - 1) dfs(board, i + 1, j, p, res); 
        if(j < board[0].length - 1) dfs(board, i, j + 1, p, res); 
        board[i][j] = c;
    }

    public TrieNode buildTrie(String[] words) {
        TrieNode root = new TrieNode();
        for(String w : words) {
            TrieNode p = root;
            for(char c : w.toCharArray()) {
                int i = c - 'a';
                if(p.next[i] == null) p.next[i] = new TrieNode();
                p = p.next[i];
           }
           p.word = w;
        }
        return root;
    }

    class TrieNode {
        TrieNode[] next = new TrieNode[26];
        String word;
    }
}

成绩:
19ms,91.42%,21ms,4.36%

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值