• Word Ladder


    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]]

  • 相关阅读:
    洛谷P1880 [NOI1995]石子合并 (区间dp
    洛谷P1012 拼数(水题 字符串
    洛谷P1071 潜伏者(水题
    微信《跳一跳》超高分攻略,轻松排行榜首
    StringUtilsd的isEmpty、isNotEmpty、isBlank、isNotBlank
    java.util.Properties类
    timer.scheduleAtFixedRate和timer.schedule的实验
    schedule() 和 scheduleAtFixedRate() 区别
    session和jsessionid有什么关系
    增加Xss过滤步骤
  • 原文地址:https://www.cnblogs.com/reynold-lei/p/4395497.html
Copyright © 2020-2023  润新知