单词搜索 II · Word Search II

https://leetcode.cn/problems/word-search-ii/description/

https://www.jiuzhang.com/solutions/word-search-ii

1.当你需要一个一个遍历字符串,矩阵或者其他的,trie帮助你优化遍历过程中可能性。

2.hash换为trire树节约空间

3.前缀

cpp 复制代码
public class Solution {
    public static int[] dx = {0, 1, -1, 0};
    public static int[] dy = {1, 0, 0, -1};
    /**
     * @param board: A list of lists of character
     * @param words: A list of string
     * @return: A list of string
     */
    public List<String> wordSearchII(char[][] board, List<String> words) {
        if (board == null || board.length == 0) {
            return new ArrayList<>();
        }
        if (board[0] == null || board[0].length == 0) {
            return new ArrayList<>();
        }
        
        boolean[][] visited = new boolean[board.length][board[0].length];
        Map<String, Boolean> prefixIsWord = getPrefixSet(words);
        Set<String> wordSet = new HashSet<>();
        
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[i].length; j++) {
                visited[i][j] = true;
                dfs(board, visited, i, j, String.valueOf(board[i][j]), prefixIsWord, wordSet);
                visited[i][j] = false;
            }
        }
        
        return new ArrayList<String>(wordSet);
    }
    
    private Map<String, Boolean> getPrefixSet(List<String> words) {
        Map<String, Boolean> prefixIsWord = new HashMap<>();
        for (String word : words) {
            for (int i = 0; i < word.length() - 1; i++) {
                String prefix = word.substring(0, i + 1);
                if (!prefixIsWord.containsKey(prefix)) {
                    prefixIsWord.put(prefix, false);
                }
            }
            prefixIsWord.put(word, true);
        }
        
        return prefixIsWord;
    }
    
    private void dfs(char[][] board,
                     boolean[][] visited,
                     int x,
                     int y,
                     String word,
                     Map<String, Boolean> prefixIsWord,
                     Set<String> wordSet) {
        if (!prefixIsWord.containsKey(word)) {
            return;
        }
        
        if (prefixIsWord.get(word)) {
            wordSet.add(word);
        }
        
        for (int i = 0; i < 4; i++) {
            int adjX = x + dx[i];
            int adjY = y + dy[i];
            
            if (!inside(board, adjX, adjY) || visited[adjX][adjY]) {
                continue;
            }
            
            visited[adjX][adjY] = true;
            dfs(board, visited, adjX, adjY, word + board[adjX][adjY], prefixIsWord, wordSet);
            visited[adjX][adjY] = false;
        }
    }
    
    private boolean inside(char[][] board, int x, int y) {
        return x >= 0 && x < board.length && y >= 0 && y < board[0].length;
    }
}
cpp 复制代码
class TrieNode {			//定义字典树的节点
    String word;
    HashMap<Character, TrieNode> children;   //使用HashMap动态开节点
    public TrieNode() {
        word = null;
        children = new HashMap<Character, TrieNode>();
    }
};


class TrieTree{
    TrieNode root;
    
    public TrieTree(TrieNode TrieNode) {
        root = TrieNode;
    }
    
    public void insert(String word) {		//字典树插入单词
        TrieNode node = root;
        for (int i = 0; i < word.length(); i++) {		
            if (!node.children.containsKey(word.charAt(i))) {
                node.children.put(word.charAt(i), new TrieNode());
            }
            node = node.children.get(word.charAt(i));
        }
        node.word = word;
    }
};

public class Solution {
    /**
     * @param board: A list of lists of character
     * @param words: A list of string
     * @return: A list of string
     */
    public int[] dx = {1, 0, -1, 0};   //搜索方向
    public int[] dy = {0, 1, 0, -1};
    
    public void search(char[][] board,			//在字典树上dfs查找
                       int x,
                       int y,
                       TrieNode root,
                       List<String> results) {
        if (!root.children.containsKey(board[x][y])) {
            return;
        }
        
        TrieNode child = root.children.get(board[x][y]);
        
        if (child.word != null) {      //如果访问到字典树叶子,将字符串压入result即可
            if (!results.contains(child.word)) {
                results.add(child.word);
            }
        }
        
        char tmp = board[x][y];
        board[x][y] = 0;  // mark board[x][y] as used
        
        for (int i = 0; i < 4; i++) {      //向四个方向dfs搜索
            if (!isValid(board, x + dx[i], y + dy[i])) {
                continue;
            }
            search(board, x + dx[i], y + dy[i], child, results);
        }
        
        board[x][y] = tmp;  // revert the mark
    }
    
    private boolean isValid(char[][] board, int x, int y) {     //检测搜索位置合法
        if (x < 0 || x >= board.length || y < 0 || y >= board[0].length) {
            return false;
        }
        
        return board[x][y] != 0;
    }
    
    public List<String> wordSearchII(char[][] board, List<String> words) {
        List<String> results = new ArrayList<String>();
        
        TrieTree tree = new TrieTree(new TrieNode());
        for (String word : words){
            tree.insert(word);
        }
        
        for (int i = 0; i < board.length; i++) {				//遍历字母矩阵,将每个字母作为单词首字母开始搜索
            for (int j = 0; j < board[i].length; j++) {
                search(board, i, j, tree.root, results);
            }
        }
        
        return results;
    }
}
cpp 复制代码
struct Node {					//定义字典树的节点
    Node * ch[26];				//因为有26个英文字母,开26个长度
    string str;
    Node() {
        for (int i = 0; i < 26; ++i)   
            ch[i] = NULL;
            str = "";
    }
};

class Solution {
public:
    vector<string> results;
    Node * root;
    void insert(Node* p, string s) {			//字典树插入单词
        int len = s.size();
        for (int i = 0; i < len; ++i) {
            if (p->ch[s[i]-'a'] == NULL)		//如果当前节点为空
                p->ch[s[i]-'a'] = new Node();	//新建节点
            p = p->ch[s[i]-'a'];                //继续遍历
        }   
        p->str = s;								//最后一个节点保存字符串
    }
    void search(vector<vector<char> > &board, vector<vector<bool> > &mask, Node* p, int x, int y) {  //在字典树上dfs查找
        if (p->str != "") {				//如果访问到字典树叶子,将字符串压入result即可
            results.push_back(p->str);
            p->str = "";
        }

        mask[x][y] = false;			//标记mask[x][y],避免重复访问
        if (y + 1 < board[0].size() && mask[x][y+1] && p->ch[board[x][y+1]-'a'] != NULL) {  //访问[x][y+1]
           search(board,mask, p->ch[board[x][y+1]-'a'], x, y+1);
        }

        if (x + 1 < board.size() && mask[x+1][y] && p->ch[board[x+1][y]-'a'] != NULL) {	//访问[x+1][y]
           search(board,mask, p->ch[board[x+1][y]-'a'], x+1, y);
        }

        if (y - 1 >= 0 && mask[x][y-1] && p->ch[board[x][y-1]-'a'] != NULL) {		//访问[x][y-1]
           search(board,mask, p->ch[board[x][y-1]-'a'], x, y-1);
        }

        if (x - 1 >= 0 && mask[x-1][y] && p->ch[board[x-1][y]-'a'] != NULL) {	//访问[x-1][y]
           search(board,mask, p->ch[board[x-1][y]-'a'], x-1, y);
        }
        mask[x][y] = true;				//搜索后mask[x][y]可以访问
    }
    /**
     * @param board: A list of lists of character
     * @param words: A list of string
     * @return: A list of string
     */
    vector<string> wordSearchII(vector<vector<char> > &board, vector<string> &words) {
        // write your code here
        root = new Node();
        int len = words.size();
        for (int i = 0; i < len; ++i) { 		//插入单词构造字典树
            insert(root, words[i]);
        }
        vector<vector<bool> > mask(board.size(), vector<bool>(board[0].size(), true));
        if (board.size() < 1) return results;
        for (int i = 0; i <board.size(); ++i) {		//遍历字母矩阵,将每个字母作为单词首字母开始搜索
            for (int j = 0; j < board[0].size(); ++j) {
               if (root->ch[board[i][j]-'a'] != NULL) {			
                    search(board, mask, root->ch[board[i][j]-'a'], i, j);  //开始dfs搜索
                 }
            }
        }
        return results;
    }
};

相关推荐
云知谷8 分钟前
【经典书籍】《代码整洁之道》第六章“对象与数据结构”精华讲解
c语言·开发语言·c++·软件工程·团队开发
遗憾是什么.10 分钟前
数据结构 -- 栈
数据结构·算法·链表
清风er10 分钟前
智能座舱开发
算法·计算机视觉
Learn Beyond Limits33 分钟前
Data Mining Tasks|数据挖掘任务
人工智能·python·神经网络·算法·机器学习·ai·数据挖掘
liuhuapeng030444 分钟前
GetMapping自动截取List<String>字符
数据结构·windows·list
Croa-vo1 小时前
Citadel SDE 面试复盘:直面硬核算法与思维挑战的双重压力
算法·面试·职场和发展
仰泳的熊猫1 小时前
1013 Battle Over Cities
数据结构·c++·算法·pat考试
渡我白衣2 小时前
字符串的陷阱与艺术——std::string全解析
网络·c++·人工智能·自然语言处理·智能路由器·信息与通信·caffe
吃不饱的得可可2 小时前
C++17常用新特性
开发语言·c++
_OP_CHEN2 小时前
算法基础篇:(七)基础算法之二分算法 —— 从 “猜数字” 到 “解难题” 的高效思维
c++·算法·蓝桥杯·二分查找·acm·二分答案·二分算法