127. Word Ladder

一开始当字符暴力搜索,TLE。

设置了提前停止的情况,依然TLE。

后来看答案是BFS,才明白怎么回事。

找转移过程中的最短途径,其实可以当做是最短路径来做。

然后问题就是怎么建立图。

想法是,到一个点,看看WORDLIST里哪个单词从现在转移,然后加入QUEUE建立搜索过程。

CODEGANKER提供的方法是,不查WORDLIST,而是把当前单词的每个字母都用a-z替换,替换之后存在于WORDLIST就加到QUEUE里,最多就25*word.length的可能性。

剩下的就是需要记住每一层加入了多少个单词,检验完进入下一层LEVEL+1。

(http://blog.csdn.net/linhuanmars/article/details/23029973)
重点是BFS的抽象。。

public int ladderLength(String beginWord, String endWord, Set<String> wordList) 
    {
        
        Queue<String> que = new LinkedList<String>();
        Set<String> visited = new HashSet<String>();
        que.add(beginWord);
        visited.add(beginWord);
        int seen = 1;
        int level = 1;
        int toSee = 0;

        while(!que.isEmpty())
        {
            String tempString = que.poll();
            seen--;

            
            for(int n = 0; n < tempString.length();n++)
            {
                char[] tempChArr = tempString.toCharArray();
                for(char m = 'a'; m <= 'z'; m++)
                {
                    tempChArr[n] = m;
                    String curString = new String(tempChArr);
                    if(curString.equals(endWord)) return level+1;

                    if(wordList.contains(curString) && !visited.contains(curString))
                    {
                        que.add(curString);
                        visited.add(curString);
                        toSee++;

                    }
                }
            }

            if(seen == 0)
            {
                seen = toSee;
                toSee = 0;
                level++;
            }
        }
        return 0;


    }

另一个需要想明白的是,深度搜索在每次迭代后,都要让变量变回原来的样子,比如VISITED如果是深度搜索,需要remove last word,以保证下次下次搜索可以使用当前单词。

而广度搜索则不用remove,因为下次不可能使用当前的单词,只能往深搜索。




二刷。

这个题还有印象。

其实是个图像题,每个Sring是个vertex,有edge到另一个vertex说明可以转化,当然要自己构建。

构建之后做一个BFS找最短路径。

BFS就一个套路,问题就在于如何判断俩单词是否可以转化。

一刷的时候我记得是看了code ganker的一个巧妙的方法。这次尝试用自己的办法,String A, String B,遍历比较不同,等于1就TRUE,否则FALSE.

结果TLE...靠,做了好久的。。
image

public class Solution {
    public int ladderLength(String beginWord, String endWord, Set<String> wordList) 
    {
        Queue<String> q = new LinkedList<String>();
        Set<String> check = new HashSet<String>();
        
        q.add(beginWord);
        check.add(beginWord);
        
        int cur = 1;
        int level = 1;
        int total = 0;

        while(!q.isEmpty())
        {
            String temp = q.poll();
            cur--;
            
            String trStr = transfer(temp,wordList,check);
            while(!trStr.equals(""))
            {
                q.add(trStr);
                check.add(trStr);
                if(trStr.equals(endWord))
                {
                    return level+1;
                }

                total++;
                
                trStr = new String(transfer(temp,wordList,check));
                
            }
            

            if(cur == 0)
            {
                cur = total;
                total = 0;
                level++;
            }
            
        }
        
        return 0;
        
    }
    
    
    public String transfer(String str1, Set<String> wordList, Set<String> check)
    {
        String res = "";
        
        Iterator iter = wordList.iterator();
        while(iter.hasNext())
        {
            String str2 = (String)iter.next();
            if(check.contains(str2))
            {
                continue;
            }
            if(isOK(str1,str2))
            {
                return str2;
            }
        }
        
        return res;
    }
    
    public boolean isOK(String str1, String str2)
    {
        int i = 0;
        int res = 0;
        //System.out.println(str1 + " " + str2);
        while(i < str1.length())
        {
            if(str1.charAt(i) != str2.charAt(i))
            {
                res++;
                if(res > 1) return false;
                
            }
            i++;
        }
    
    
        if(res == 0) return false;
        return true;
    }
    
}

然后介绍下CODE GANKER的办法。

比如"a",他最多能有25个edge就是"b","c","d".."z".
比如"ab",最多是"aa","ac","ad"..."bb","cb","db"..
总之一次只能改变1个字母嘛,每一位有26种选择(算上它自己)。

因为单词长度不会很长,所以可以穷举。。每位每次变一个,看在不在LIST里。。在就说明可以转化。

把中间的判断部分改一下就行了。。

public class Solution {
    public int ladderLength(String beginWord, String endWord, Set<String> wordList) 
    {
        Queue<String> q = new LinkedList<String>();
        Set<String> check = new HashSet<String>();
        
        q.add(beginWord);
        check.add(beginWord);
        
        int cur = 1;
        int level = 1;
        int total = 0;

        while(!q.isEmpty())
        {
            String temp = q.poll();
            cur--;
            
            for(int i = 0; i < temp.length();i++)
            {
                char[] tempArray = temp.toCharArray();
                for(char j = 'a'; j <= 'z';j++)
                {
                    tempArray[i] = j;
                    String newString = new String(tempArray);
                    
                    if(!check.contains(newString) && wordList.contains(newString))
                    {
                        if(newString.equals(endWord)) return level+1;
                        
                        check.add(newString);
                        q.add(newString);
                        total++;
                    }
                    
                    
                }
            }
            

            if(cur == 0)
            {
                cur = total;
                total = 0;
                level++;
            }
            
        }
        
        return 0;
        
    }
   
}

看一刷写的记录,我一刷居然用的DFS,然后TLE。我完全记不得当时的情况,对于当时唯一还存留的印象就是我当时的姓名和性别。

肯定有DFS的做法,介于我现在做题把头做大了(胖头鱼YYF),就不看了。。



三刷。
我曾经想象过很多次这个时刻,被拒的时刻,可它来临的时候,我依然觉得很难过。

这个题印象比较深,是BFS的图形题。

搜索的时候有一个桥办法是26个字母轮一遍。其实应该试试如何正儿八经做。。

时间复杂度……
depth = n, brach = 26 so.. 26 ^ n
这是2个内部loop。 外面还有个while loop,可能所有单词都要来一遍,所以n
Time Complexity: O(n(26^n))
空间复杂度……
Queue + tempString(charArray) = O(N)? 是这样吧。。 我对这个概念混淆很严重,比如类似于combination中间产生的tempList,倘若不是为了迭代,如果最终要加入结果集,那算不算占用了空间。。毕竟最终结果本身就是O(n * 2^n)

Space Complexity: O(n)

public class Solution {
    public int ladderLength(String beginWord, String endWord, Set<String> wordList) {
        if (beginWord.equals(endWord)) return 2;
        Queue<String> q = new LinkedList<>();
        q.add(beginWord);
        int res = 1;
        int left = 1;
        int total = 0;
        while (!q.isEmpty()) {
            String str = q.poll();
            for (int i = 0; i < str.length(); i++) {
                char[] chArray = str.toCharArray();
                for (char j = 'a'; j <= 'z'; j++) {
                    chArray[i] = j;
                    String s = new String(chArray);
                    if (s.equals(endWord)) {
                        return res + 1;
                    }
                    if (wordList.contains(s)) {
                        wordList.remove(s);
                        q.offer(s);
                        total++;
                        
                    }
                }
            }
            left--;
            if (left == 0) {
                left = total;
                total = 0;
                res++;
            }
        }
        return 0;
    }
}

看看递归。
网上的2头同时search,这样每次从少的那边找,不过要多建俩set

Time Complexity O(n * 26^n)
Space: 两个SET,运行过程中的SETS,charArray O(n) + O(n) + O(n) + O(k) = O(n)
觉得运行过程中的SET算一个,比如用一个全局变量。。。每次clear。。

public class Solution {
    public int ladderLength(String beginWord, String endWord, Set<String> wordList) {
        if (beginWord.equals(endWord)) return 2;
        Set<String> set1 = new HashSet<>();
        Set<String> set2 = new HashSet<>();
        set1.add(beginWord);
        set2.add(endWord);
        wordList.remove(beginWord);
        wordList.remove(endWord);
        
        return bfs(wordList, set1, set2, 2);
    }
    
    public int bfs(Set<String> wordList, Set<String> set1, Set<String> set2, int depth) {
        Set<String> nextLevel = new HashSet<>();
        for (String s: set1) {
            for (int i = 0; i < s.length(); i++) {
                char[] chArray = s.toCharArray();
                for (char j = 'a'; j <= 'z'; j++) {
                    chArray[i] = j;
                    String tempS = new String(chArray);
                    if (set2.contains(tempS)) return depth;
                    if (wordList.contains(tempS)) {
                        wordList.remove(tempS);
                        nextLevel.add(tempS);
                    }
                }
            }
        }
        
        if (nextLevel.size() == 0) return 0;
        if (nextLevel.size() <= set2.size()) {
            return bfs(wordList, nextLevel, set2, depth + 1);
        } else {
            return bfs(wordList, set2, nextLevel, depth + 1);
        }
    }
}
posted @ 2016-11-10 07:25  哇呀呀..生气啦~  阅读(138)  评论(0)    收藏  举报