单词接龙

给定两个单词(beginWord 和 endWord)和一个字典,找到从 beginWord 到 endWord 的最短转换序列的长度。转换需遵循如下规则:

每次转换只能改变一个字母。
转换过程中的中间单词必须是字典中的单词。
说明:

如果不存在这样的转换序列,返回 0。
所有单词具有相同的长度。
所有单词只由小写字母组成。
字典中不存在重复的单词。
你可以假设 beginWord 和 endWord 是非空的,且二者不相同。
示例 1:

输入:
beginWord = "hit",
endWord = "cog",
wordList = ["hot","dot","dog","lot","log","cog"]

输出: 5

解释: 一个最短转换序列是 "hit" -> "hot" -> "dot" -> "dog" -> "cog",
返回它的长度 5。
示例 2:

输入:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log"]

输出: 0

解释: endWord "cog" 不在字典中,所以无法进行转换。

方法1: DFS

  • 使用队列广度搜索,时间复杂度为O(n^2*L)
import java.util.*;
class Solution {
    public int ladderLength(String beginWord, String endWord, List<String> wordList) {
        Queue<String> queue = new LinkedList<String>();
        boolean[] path = new boolean[wordList.size()];
        String temp;
        int len = 0;
        queue.add(beginWord);
        while(!queue.isEmpty()){
            int size = queue.size();
            while(size -- >0){
                temp = queue.remove();
                if(temp.equals(endWord)) return len+1;
                for(int i = 0 ;i<wordList.size();i++){
                    String p = wordList.get(i);
                    if(isEquals(temp,p) && path[i]==false){
                        path[i] = true;
                        queue.add(p);
                    }
                }
            }
            len++;
        }
        return 0;
    }
    public boolean isEquals(String x, String y){
        int count  = 0;
        for(int i = 0;i<y.length();i++){
            if(x.charAt(i) != y.charAt(i)){
                count ++;
            }
            if(count>1) break;
        }
        return count <= 1;
    }
}

方法2:双向DFS

  • 使用双向DFS,从头尾两个方向向中间搜索,当两端搜索的集合包含重叠元素时,表示两端可以在该点连同。
  • 当第一次听说双向DFS,以为使用两个队列,但判断是否包含重叠元素时队列不好判断,所以使用Set容器比较方便。set每次保存搜索到的一层元素。
  • 对于头尾集合,保证每次都是从元素最少的集合中开始向下一层搜索,减少搜索时间。
  • 时间复杂度:每个元素都要放入set遍历一次,对于每个单词的每一位,都要用a-z替换一次,判断替换后的单词是否存在在另一个set中,hashset查询复杂度O(L),所以总的时间复杂度为 n26L^2

算法流程:

  1. 构建头尾两个集合,保证头集合为元素最少的集合
  2. 从头集合开始搜索,当搜索到的元素在尾集合时,则说明已经到达,结束搜索
  3. 否则 将搜索到的元素放入新的头集合中,进行下一层搜索。
import java.util.*;
class Solution {
    public int ladderLength(String beginWord, String endWord, List<String> wordList) {
        Set<String> wordSet = new HashSet<>(wordList);
        Set<String> startSet = new HashSet<>();
        Set<String> endSet = new HashSet<>();
        startSet.add(beginWord);
        endSet.add(endWord);
        int len =  1;
        char[] ch;
        Set<String> temp;
        if(!wordSet.contains(endWord))  return 0;
        while(!startSet.isEmpty() && !endSet.isEmpty()){
            len ++;
            if(startSet.size() > endSet.size() ){
                temp = endSet;
                endSet = startSet;
                startSet = temp;
            }
         //   System.out.print(startSet.toString());
         //   System.out.println(endSet.toString());
           Set<String> newhead = new HashSet<>();
            for(String p : startSet){
                ch = p.toCharArray();
                for(int i = 0;i < p.length();i++){
                    char k = ch[i];
                    for(char c = 'a';c <='z';c++){
                        if(c == k)  continue;
                        ch[i] = c;
                        String res = String.valueOf(ch);
                      //  System.out.println(res);
                        if(endSet.contains(res))
                                 return len;
                        if(wordSet.contains(res)){
                         //   System.out.println(res);
                             wordSet.remove(res);
                             newhead.add(res);
                        }
                    }
                    ch[i] = k;
                }
            }
            startSet = newhead;
        }
        return 0;
    }
}
posted @ 2019-08-01 15:20  御心飞行  阅读(160)  评论(0编辑  收藏  举报