强化二 字典树 Trie

Trie 的考点

  • 实现一个 Trie
  • 比较 Trie 和 Hash 的优劣
  • 字符矩阵类问题使用 Trie 比 Hash 更高效
  • hash和trie查找一个单词在不在都是O(L) 但是由于trie用到L次寻址操作 所以比hash慢

Hash vs Trie

  • 互相可替代
  • Trie 耗费更少的空间 单次查询 Trie 耗费更多的时间 (复杂度相同,Trie 系数大一些)

注意:

  • 不要忘记初始化root

思路:
其实就是实现两个操作

  • 插入一个单词
  • 查找某个单词或前缀是否存在

208 Implement Trie (Prefix Tree)
211 Add and Search Word - Data structure design
*425 Word Squares 从给定字典中 找出能组成对称矩阵的所有组合
*212 Word Search II 在给定字符矩阵中 找所有字典中的词

208 Implement Trie (Prefix Tree)

class Trie {
    class TrieNode{
        TrieNode[] children;
        boolean isWord;
        TrieNode(){
            children = new TrieNode[26];
            isWord = false;
        }
    }

    TrieNode root;
    /** Initialize your data structure here. */
    public Trie() {
        root = new TrieNode();
    }
    
    /** Inserts a word into the trie. */
    public void insert(String word) {
        TrieNode current = root;
        for(char c : word.toCharArray()){
            int index = c - 'a';
            if(current.children[index]==null){
                current.children[index] = new TrieNode();
            }
            current = current.children[index];
        }
        current.isWord = true;
    }
    
    /** Returns if the word is in the trie. */
    public boolean search(String word) {
        TrieNode current = root;
        for(char c : word.toCharArray()){
            int index = c - 'a';
            if(current.children[index]==null){
                return false;
            }
            current = current.children[index];
        }
        return current.isWord;
    }
    
    /** Returns if there is any word in the trie that starts with the given prefix. */
    public boolean startsWith(String word) {
        TrieNode current = root;
        for(char c : word.toCharArray()){
            int index = c - 'a';
            if(current.children[index]==null){
                return false;
            }
            current = current.children[index];
        }
        return true;
    }
}

211 Add and Search Word - Data structure design

class WordDictionary {
    class Node{
        Node[] children;
        boolean isWord;
        Node(){
            children = new Node[26];
            isWord = false;
        }
    }
    Node root;
    /** Initialize your data structure here. */
    public WordDictionary() {
        root = new Node();
    }
    
    /** Adds a word into the data structure. */
    public void addWord(String word) {
        Node current = root;
        for(char c : word.toCharArray()){
            int index = c - 'a';
            if(current.children[index]==null){
                current.children[index] = new Node();
            }
            current = current.children[index];
        }
        current.isWord = true;
    }
    
    /** Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. */
    public boolean search(String word) {
        return find(word, 0, root);
    }
    
    private boolean find(String word, int index, Node node){
        if(index == word.length())
            return node.isWord;
        char c = word.charAt(index);
        if(c=='.'){
            for(int j=0; j<26; j++){
                    if(node.children[j]!=null){
                        if(find(word, index+1, node.children[j]))
                            return true;
                    }
                }
                return false;
        }else{
            return node.children[c-'a']!=null && find(word, index+1, node.children[c-'a']);
        }
    }
}

/**
 * Your WordDictionary object will be instantiated and called as such:
 * WordDictionary obj = new WordDictionary();
 * obj.addWord(word);
 * boolean param_2 = obj.search(word);
 */

425 Word Squares 从给定字典中 找出能组成对称矩阵的所有组合

class Solution {
    static class TrieNode{
        TrieNode[] children;
        boolean isWord;
        Set<String> list;
        TrieNode(){
            children = new TrieNode[26];
            isWord = false;
            list = new HashSet<>();
        }
    }
    static TrieNode root;
    private static void build(String[] words){
        for(String s : words){
            buildHelper(s);
        }
    }
    private static void buildHelper(String s){
        TrieNode current = root;
        for(int i=0; i<s.length(); i++){
            char c = s.charAt(i);
            int index = c-'a';
            if(current.children[index]==null)
                current.children[index] = new TrieNode();
            current.list.add(s);
            current = current.children[index];
        }
        current.isWord = true;
        current.list.add(s);
    }

    private static Set<String> getWordsWithPrefix(String prefix){
        Set<String> result = new HashSet<>();
        TrieNode current = root;
        for(int i=0; i<prefix.length(); i++){
            char c = prefix.charAt(i);
            int index = c-'a';
            if(current.children[index]==null)
                return result;
            current = current.children[index];
        }
        return current.list;
    }
    
    public static List<List<String>> wordSquares(String[] words) {
        List<List<String>> results = new ArrayList<>();
        if(words==null || words.length==0 || words[0].length()==0)
            return results;
        root = new TrieNode();
        build(words);
        helper(words, results, new ArrayList<String>());
        return results;
    }
    
    private static void helper(String[] words, List<List<String>> results, List<String> subset){
        int size = words[0].length();
        if(subset.size() == size){
            results.add(new ArrayList<String>(subset));
            return;
        }
        StringBuilder sb = new StringBuilder();
        for(String s : subset){
            sb.append(s.charAt(subset.size()));
        }
        String prefix = sb.toString();
        Set<String> set = getWordsWithPrefix(prefix);
        for(String s : set){
            subset.add(s);
            helper(words, results, subset);
            subset.remove(subset.size()-1);
        }
    } 
}

212 Word Search II 在给定字符矩阵中 找所有字典中的词

  • 用hashmap
class Solution {
    public List<String> findWords(char[][] board, String[] words) {
        Set<String> prefixs = new HashSet<>();
        Set<String> wordSet = new HashSet<>();
        for(int j=0; j<words.length; j++){
            String word = words[j];
            wordSet.add(word);
            for(int i=0; i<word.length(); i++){
                String prefix = word.substring(0, i+1);
                prefixs.add(prefix);
            }
        }
        boolean[][] visited = new boolean[board.length][board[0].length];
        Set<String> results = new HashSet<>();
        for(int i=0; i<board.length; i++){
            for(int j=0; j<board[0].length; j++){
                visited[i][j] = true;
                helper(board, visited, i, j, prefixs, wordSet, results, String.valueOf(board[i][j]));
                visited[i][j] = false;
            }
        }
        return new ArrayList<String>(results);
    }
    private void helper(char[][] board, boolean[][] visited, int x, int y, Set<String> prefixs, Set<String> wordSet, Set<String> results, String temp){ 
        if(wordSet.contains(temp)){
            results.add(temp);
        }
        if(!prefixs.contains(temp))
            return;
        
        int[] dirx = {1,-1,0,0};
        int[] diry = {0,0,1,-1};
        for(int i=0; i<4; i++){
            if(isValid(board, x+dirx[i], y+diry[i], visited)){
                visited[x+dirx[i]][y+diry[i]] = true;
                helper(board, visited, x+dirx[i], y+diry[i], prefixs, wordSet, results, temp+board[x+dirx[i]][y+diry[i]]);
                visited[x+dirx[i]][y+diry[i]] = false;
            }
        }   
    }
    private boolean isValid(char[][] board,int x, int y, boolean[][] visited){
        if(x>=0 && x<board.length && y>=0 && y<board[0].length && visited[x][y]==false)
            return true;
        return false;
    }
}
  • 用trie
class Solution {
    static class TrieNode{
        TrieNode[] children;
        TrieNode(){
            children = new TrieNode[26];
        }
    }
    static TrieNode root;
    private static void build(String[] words){
        for(String word: words){
            builderHelper(word);
        }
    }
    private static void builderHelper(String word){
        TrieNode current = root;
        for(char c : word.toCharArray()){
            int index = c - 'a';
            if(current.children[index]==null)
                current.children[index] = new TrieNode();
            current = current.children[index];
        }
    }

    private static boolean startWith(String word){
        TrieNode current = root;
        for(char c : word.toCharArray()){
            int index = c - 'a';
            if(current==null || current.children[index]==null)
                return false;
            current = current.children[index];
        }
        return true;
    }

    public static List<String> findWords(char[][] board, String[] words) {
        Set<String> results = new HashSet<>();
        root = new TrieNode();
        build(words);
        Set<String> set = new HashSet<>();
        for(String s: words){
            set.add(s);
        }
        boolean[][] visited = new boolean[board.length][board[0].length];
        for(int i=0; i<board.length; i++){
            for(int j=0; j<board[0].length; j++){
                StringBuilder sb = new StringBuilder();
                sb.append(board[i][j]);
                visited[i][j] = true;
                helper(i, j, board, set, results, sb, visited);
                visited[i][j] = false;
            }
        }
        List<String> solutions = new ArrayList<>();
        for(String s: results){
            solutions.add(s);
        }
        return solutions;
    }
    private static void helper(int row, int col, char[][] board, Set<String> set, Set<String> results, StringBuilder sb, boolean[][] visited){

        if(set.contains(sb.toString()))
            results.add(sb.toString());
        int[] dirx = {1, -1, 0, 0};
        int[] diry = {0, 0, -1, 1};
        for(int i=0; i<4; i++){
            int x = row + dirx[i];
            int y = col + diry[i];
            if(!valid(x, y, visited)){
                continue;
            }
            sb.append(board[x][y]);
            if(!startWith(sb.toString())){
                sb.deleteCharAt(sb.length()-1);
                continue;
            }
            visited[x][y] = true;
            helper(x, y, board, set, results, sb, visited);
            sb.deleteCharAt(sb.length()-1);
            visited[x][y] = false;
        }
    }
    private static boolean valid(int x, int y, boolean[][] visited){
        return x>=0 && x<visited.length && y>=0 && y<visited[0].length && !visited[x][y];
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容

  • 背景 一年多以前我在知乎上答了有关LeetCode的问题, 分享了一些自己做题目的经验。 张土汪:刷leetcod...
    土汪阅读 12,719评论 0 33
  • 算法思想贪心思想双指针排序快速选择堆排序桶排序荷兰国旗问题二分查找搜索BFSDFSBacktracking分治动态...
    第六象限阅读 3,021评论 0 0
  • LeetCode 刷题随手记 - 第一部分 前 256 题(非会员),仅算法题,的吐槽 https://leetc...
    蕾娜漢默阅读 17,676评论 2 36
  • 《摆渡人1》给我们讲述了少女迪伦遭遇车祸丧生,由摆渡人崔斯坦引领走出荒原去往另一个世界,但最后为了爱,他们越过重重...
    _桃李不言_阅读 966评论 0 1
  • 一整天的订货,很是烧脑!经过跟工厂的沟通,我们明确了几点:老板要明确自己的目标。要带领团队一起打造目标市场。穷日子...
    TA77范丽萍阅读 158评论 0 0