Word Ladder

系统 1865 0

Given two words ( start  and  end ), and a dictionary, find all transformation sequence(s) from  start  to  end , such that:

  1. Only one letter can be changed at a time
  2. Each intermediate word must exist in the dictionary

 

Note:

  • All words have the same length.
  • All words contain only lowercase alphabetic characters.

尝试用Trie 来实现这个。

最后TLE(out of time),不过算法已经正确了。 

使用Trie,扩展性更好。 可以时时的加减dict里面的word, 也可以被多次调用。

      
          1
      
      
        package
      
      
         leetcode;


      
      
          2
      
      
          3
      
      
        import
      
      
         java.util.ArrayList;


      
      
          4
      
      
        import
      
      
         java.util.HashSet;


      
      
          5
      
      
        import
      
      
         java.util.Iterator;


      
      
          6
      
      
        import
      
      
         java.util.List;


      
      
          7
      
      
        import
      
      
         java.util.Set;


      
      
          8
      
      
          9
      
      
        //
      
      
        implement wordLadder with Trie.
      
      
         10
      
      
        /*
      
      
         11
      
      
         * 如果这个函数要多次被调用,怎么办?


      
      
         12
      
      
         * 因为我每次都用挨个修改字母的办法来寻找新word,但如果能先对dictionary做个预处理,弄个从word到set of words之间的mapping,那么每轮BFS就可以省去寻找新词的时间。预处理字典的复杂度也是O(size of dictionary) * (length of string) * 26。最终可以用一个Hash<String, Set<String>>来表示这个mapping关系。


      
      
         13
      
      
         * 


      
      
         14
      
      
         * 如果这个字典要增加/移除单词怎么办?


      
      
         15
      
      
         * 增加的话,只需要对新单词做同样的事情:修改每个字母找下一个单词,然后那个被找到下一个单词的mapping里同时也添加进新单词。因为这个关系是可互换的,如果wordA => wordB, 那么wordB => wordA。


      
      
         16
      
      
         * 删除的时候同理,对于map.get(toBeRemoved)里的所有单词的mapping集合都删掉这个toBeRemoved,然后再从map里面去掉它自己,写出来的代码大概是这样:


      
      
         17
      
      
         * for (String s : map.get(toBeRemoved)) map.get(s).remove(toBeRemoved);


      
      
         18
      
      
         * map.remove(toBeRemoved);


      
      
         19
      
      
         * 这个地方我一开始没注意到可以互换,以为还得预处理一个反方向的mapping,经过面试官两次提醒才发现了这个规律……


      
      
         20
      
      
         * 


      
      
         21
      
      
         * 如果这个字典变得很庞大,这个mapping和字典本身就太占空间了,怎么处理?


      
      
         22
      
      
         * 用trie记录所有单词,每个node用一个bit记录这个node是否为一个单词,并且有一个set<myTrieNode>的field记录他可以变成的其他单词。至于如何构建这个field,利用trie的特性,可以用回溯的方法非常简单地找到可变过去的单词(在碰到公共ancestor之前,路径上的node个数必须相同,这个用于保证长度,并且至多只有一个字母不同,用于满足mapping的条件)


      
      
         23
      
      
         * 至此……时间终于用完了,问了下他的team的情况,就结束了……


      
      
         24
      
      
         * 


      
      
         25
      
      
         * 
      
      
        */
      
      
         26
      
      
         27
      
      
        class
      
      
         myTrieNode{


      
      
         28
      
      
            Boolean isWord;


      
      
         29
      
      
            myTrieNode[] childList;


      
      
         30
      
      
            Integer freq;


      
      
         31
      
      
        char
      
      
         val;


      
      
         32
      
      
            String word;


      
      
         33
      
      
         34
      
      
        public
      
       myTrieNode(){
      
        //
      
      
        use to generate root of Trie
      
      
         35
      
      
        this
      
      .freq = 0
      
        ;


      
      
         36
      
      
        this
      
      .childList = 
      
        new
      
       myTrieNode[26
      
        ];


      
      
         37
      
      
        this
      
      .isWord = 
      
        false
      
      
        ;


      
      
         38
      
      
            }


      
      
         39
      
      
         40
      
      
        public
      
       myTrieNode(
      
        char
      
      
         c){


      
      
         41
      
      
        this
      
      .val =
      
         c;


      
      
         42
      
      
        this
      
      .freq = 1
      
        ;


      
      
         43
      
      
        this
      
      .childList = 
      
        new
      
       myTrieNode[26
      
        ];


      
      
         44
      
      
            }


      
      
         45
      
      
         46
      
      
        public
      
      
         String containsWord(String s){


      
      
         47
      
      
        if
      
      (s == 
      
        null
      
       || s.length() == 0
      
        ){


      
      
         48
      
      
        if
      
      (
      
        this
      
      .word != 
      
        null
      
       && 
      
        this
      
      .isWord == 
      
        true
      
      ) 
      
        return
      
      
        this
      
      
        .word;


      
      
         49
      
      
        else
      
      
        return
      
       ""
      
        ;


      
      
         50
      
      
                }


      
      
         51
      
      
        int
      
       len =
      
         s.length();


      
      
         52
      
               myTrieNode cur = 
      
        this
      
      
        ;


      
      
         53
      
      
        for
      
      (
      
        int
      
       i = 0; i < len; i ++
      
        ){


      
      
         54
      
      
        char
      
       c =
      
         s.charAt(i);


      
      
         55
      
      
        if
      
      (cur.childList[c - 'a'] != 
      
        null
      
      
        ){


      
      
         56
      
                       cur = cur.childList[c - 'a'
      
        ];


      
      
         57
      
                   }
      
        else
      
      
        {


      
      
         58
      
      
        return
      
      
        null
      
      
        ;


      
      
         59
      
      
                    }


      
      
         60
      
      
                }


      
      
         61
      
      
        return
      
       cur.isWord == 
      
        true
      
       ? cur.word : 
      
        null
      
      
        ;


      
      
         62
      
      
            }


      
      
         63
      
      
        }


      
      
         64
      
      
        class
      
      
         myTrie{


      
      
         65
      
      
            myTrieNode root;


      
      
         66
      
      
         67
      
      
        public
      
      
         myTrie(){


      
      
         68
      
      
        this
      
      .root = 
      
        new
      
      
         myTrieNode();


      
      
         69
      
      
            }


      
      
         70
      
      
         71
      
      
        public
      
      
        void
      
      
         insert(String word){


      
      
         72
      
      
        if
      
      (word == 
      
        null
      
       || word.length() == 0) 
      
        return
      
      
        ;


      
      
         73
      
      
        int
      
       len =
      
         word.length();


      
      
         74
      
               myTrieNode cur = 
      
        this
      
      
        .root;


      
      
         75
      
      
        for
      
      (
      
        int
      
       i = 0; i < len; i ++
      
        ){


      
      
         76
      
      
        char
      
       c =
      
         word.charAt(i);


      
      
         77
      
      
        if
      
      (cur.childList[c - 'a'] == 
      
        null
      
      
        ){


      
      
         78
      
                       cur.childList[c - 'a'] = 
      
        new
      
      
         myTrieNode(c);


      
      
         79
      
                   }
      
        else
      
      
        {


      
      
         80
      
                       cur.childList[c - 'a'].freq ++
      
        ;


      
      
         81
      
      
                    }


      
      
         82
      
                   cur = cur.childList[c - 'a'
      
        ];


      
      
         83
      
      
        if
      
      (i == word.length() - 1
      
        ){


      
      
         84
      
                       cur.isWord = 
      
        true
      
      
        ;


      
      
         85
      
                       cur.word =
      
         word;


      
      
         86
      
      
                    } 


      
      
         87
      
      
                }


      
      
         88
      
      
            }


      
      
         89
      
      
         90
      
      
        }


      
      
         91
      
      
        public
      
      
        class
      
      
         WordLadder {


      
      
         92
      
      
         93
      
      
         94
      
      
        private
      
      
        static
      
      
         myTrie trie;


      
      
         95
      
      
        private
      
      
        static
      
       List<List<String>>
      
         result;


      
      
         96
      
      
        public
      
      
        static
      
       List<List<String>> findLadders(String start, String end, Set<String>
      
         dict) {


      
      
         97
      
                   trie =
      
         generateTrie(dict);


      
      
         98
      
      
                    trie.insert(end);


      
      
         99
      
                   result = 
      
        new
      
       ArrayList<List<String>>
      
         ();


      
      
        100
      
                   ArrayList<String> row = 
      
        new
      
       ArrayList<String>
      
        ();


      
      
        101
      
      
                    row.add(start);


      
      
        102
      
                   findLadderSequence(start, end, row, 
      
        new
      
       HashSet<String>
      
        ());


      
      
        103
      
      
        return
      
      
         result;


      
      
        104
      
      
                }


      
      
        105
      
      
        106
      
      
        private
      
      
        static
      
      
        void
      
       findLadderSequence(String start, String end, ArrayList<String> row, HashSet<String>
      
         usedSet){


      
      
        107
      
      
        if
      
      
        (start.equals(end)){


      
      
        108
      
      
                        result.add(row);


      
      
        109
      
      
                    }


      
      
        110
      
                   myTrieNode cur =
      
         trie.root;


      
      
        111
      
                   myTrieNode next =
      
         cur;


      
      
        112
      
      
        for
      
      (
      
        int
      
       i = 0; i < start.length(); i ++
      
        ){


      
      
        113
      
      
        char
      
       c =
      
         start.charAt(i);


      
      
        114
      
      
        for
      
      (
      
        int
      
       j = 0; j < 26; j ++
      
        ){


      
      
        115
      
      
        if
      
      (cur.childList[j] != 
      
        null
      
       && cur.childList[j].val ==
      
         c){


      
      
        116
      
                               next =
      
         cur.childList[j];


      
      
        117
      
      
                            }


      
      
        118
      
      
        if
      
      (cur.childList[j] != 
      
        null
      
       && cur.childList[j].val !=
      
         c){


      
      
        119
      
                               String tmp = cur.childList[j].containsWord(start.substring(i + 1
      
        ));


      
      
        120
      
      
        if
      
      (tmp != 
      
        null
      
       && !
      
        usedSet.contains(tmp)){


      
      
        121
      
      
                                    row.add(tmp);


      
      
        122
      
      
                                    usedSet.add(tmp);


      
      
        123
      
                                   findLadderSequence(tmp, end, 
      
        new
      
       ArrayList<String>(row), 
      
        new
      
       HashSet<String>
      
        (usedSet));


      
      
        124
      
                                   row.remove(row.size() - 1
      
        );


      
      
        125
      
      
                                    usedSet.remove(tmp);


      
      
        126
      
      
                                }


      
      
        127
      
      
                            }


      
      
        128
      
      
                        }


      
      
        129
      
                       cur =
      
         next;


      
      
        130
      
      
                    }


      
      
        131
      
      
        132
      
      
                }


      
      
        133
      
      
        134
      
      
        private
      
      
        static
      
       myTrie generateTrie(Set<String>
      
         dict){


      
      
        135
      
                   myTrie trie = 
      
        new
      
      
         myTrie();


      
      
        136
      
      
        if
      
      (dict.isEmpty()) 
      
        return
      
      
         trie;


      
      
        137
      
      
        //
      
      
        generate Trie for dictionary
      
      
        138
      
                   Iterator it =
      
         dict.iterator();


      
      
        139
      
      
        while
      
      
        (it.hasNext()){


      
      
        140
      
                       String word =
      
         (String)it.next();


      
      
        141
      
      
                        trie.insert(word);


      
      
        142
      
      
                    }


      
      
        143
      
      
        return
      
      
         trie;


      
      
        144
      
      
                }


      
      
        145
      
      
        146
      
      
        public
      
      
        static
      
      
        void
      
      
         main(String[] args){


      
      
        147
      
               String start = "hit"
      
        ;


      
      
        148
      
               String end = "cog"
      
        ;


      
      
        149
      
               Set<String> dict = 
      
        new
      
       HashSet<String>
      
        ();


      
      
        150
      
               dict.add("hot"
      
        );


      
      
        151
      
               dict.add("dot"
      
        );


      
      
        152
      
               dict.add("dog"
      
        );


      
      
        153
      
               dict.add("lot"
      
        );


      
      
        154
      
               dict.add("log"
      
        );


      
      
        155
      
      
                findLadders(start, end, dict);


      
      
        156
      
      
                System.out.println(result);


      
      
        157
      
      
            }


      
      
        158
      
       }
    

 Output:

[[hit, hot, dot, lot, log, cog],

[hit, hot, dot, lot, log, dog, cog],

[hit, hot, dot, dog, cog],

[hit, hot, dot, dog, log, cog],

[hit, hot, lot, dot, dog, cog],

[hit, hot, lot, dot, dog, log, cog],

[hit, hot, lot, log, cog],

[hit, hot, lot, log, dog, cog]]

Word Ladder


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论