leetcode127.Word Ladder (单双向BFS)

Given two words (beginWord and endWord), and a dictionary’s word list, find the length of shortest transformation sequence from beginWord to endWord, such that:

Only one letter can be changed at a time.
Each transformed word must exist in the word list. Note that beginWord is not a transformed word.
Note:

Return 0 if there is no such transformation sequence.
All words have the same length.
All words contain only lowercase alphabetic characters.
You may assume no duplicates in the word list.
You may assume beginWord and endWord are non-empty and are not the same.
Example 1:

Input:
beginWord = “hit”,
endWord = “cog”,
wordList = [“hot”,“dot”,“dog”,“lot”,“log”,“cog”]

Output: 5

Explanation: As one shortest transformation is “hit” -> “hot” -> “dot” -> “dog” -> “cog”,
return its length 5.

Example 2:

Input:
beginWord = “hit”
endWord = “cog”
wordList = [“hot”,“dot”,“dog”,“lot”,“log”]

Output: 0

Explanation: The endWord “cog” is not in wordList, therefore no possible transformation.

给出一个beginWord,一个endWord,和一个wordList
让beginWord中每次变动一个字母后,得是wordList里面的某一个单词,而且单词不能重复使用,问经过几次变动可以变成endWord,返回step数,如果不能达到要求,返回0

思路:
单向BFS 和 双向BFS (参考某大牛的方法)

单向BFS思路:
比如Example1
beginWord = “hit”, 是开始的queue
取出hit,按位从’a’变到’z’,看变动后是否在wordList中,如果在,加入queue作下一level的展开
比如第一位’h’,从’a’到’z’可以变成’ait’, ‘bit’, …, ‘zit’, 发现都不在wordList里
再变第2位’i’,从’a’到’z’可以变成’hat’, ‘hbt’, …, ‘hzt’,其中’hot’在wordList里,加入queue,同时为了避免重复,从wordList中删除’hot’
同理第3位,发现没有

所以下一level的展开对象是’hot’

如此一步一步展开,直到得到endWord,如果所有位都处理完仍没有,返回0

time complexity: O(n * 26len)

双向BFS:
交替展开beginWord和endWord,直到在中间某一点相遇
beginWord的展开存在q1
endWord的展开存在q2
如果中间q1展开的单词存在q2中,则返回step+1

q1, q2中的某一个中间结果都不在wordList中则返回0

trick:
因为是交替展开,每次选q1和q2中较小size的展开,可以节省时间复杂度

注意
List和HashSet的contains方法
因为中间要判断单词是否存在于wordList中,要用到contains方法,
而wordList是List类型,List的contains方法底层实现是for loop,O(n)复杂度
而HashSet的contains底层实现是直接利用key,O(1)复杂度

本题如果直接用List,时间是967ms, 而转成HashSet后是13ms

双向BFS:

//13ms
    public int ladderLength(String beginWord, String endWord, List<String> wordList) {
        HashSet<String> dict = new HashSet<String>(wordList);
        if (!dict.contains(endWord)) {
            return 0;
        }
        
        int len = beginWord.length();
        
        HashSet<String> q1 = new HashSet<String>() {{add(beginWord);}};
        HashSet<String> q2 = new HashSet<String>() {{add(endWord);}};
        
        int step = 0;
        
        while (!q1.isEmpty() && !q2.isEmpty()) {
            step ++;
            
            if (q1.size() > q2.size()) {  //swap q1 and q2..
                HashSet<String> tmp = q2;
                q2 = q1;
                q1 = tmp;
            }
            
            HashSet<String> queue = new HashSet<>();
            
            for (String word : q1) {
                char[] cWord = word.toCharArray();
                for (int i = 0; i < len; i++) {
                    char before = cWord[i];
                    
                    for (char c = 'a'; c <= 'z'; c++) {
                        cWord[i] = c;
                        String changed = String.valueOf(cWord);
                        
                        if (q2.contains(changed)) {
                            return step + 1;
                        }
                        
                        if (dict.contains(changed)) {
                            queue.add(changed);
                            dict.remove(changed);
                        }
                        
                    }
                    
                    cWord[i] = before;
                }
            }
            
            q1 = queue;
        }
        
        return 0;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝羽飞鸟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值