Leetcode Word Ladder

探讨了从一个单词通过一系列变换到达另一个单词的问题,使用深度优先搜索(DFS)和广度优先搜索(BFS)两种算法解决,并通过哈希表优化查找效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

  1. Only one letter can be changed at a time.
  2. Each transformed word must exist in the word list. Note thatbeginWord is not a transformed word.

For example,

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

As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog",
return its length 5.

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.

UPDATE (2017/1/20):
The wordList parameter had been changed to a list of strings (instead of a set of strings). Please reload the code definition to get the latest changes.


自然而然想到了DFS,代码如下:

    class Solution {  
    public:  
        int ladderLength(string beginWord, string endWord, vector<string>& wordList) {  
            unordered_set<string> dict;
            for(int i=0;i<wordList.size();i++)
                dict.insert(wordList[i]);
            
            if(beginWord.size() != endWord.size())  
                return 0;  
            if(beginWord.empty() || endWord.empty() || wordList.empty())  
                return 0;  
              
            int result = Tran(beginWord,endWord,dict);  
            if(result == INT_MAX)  
                return 0;  
            else  
                return result;  
        }  
              
        int Tran(string beginWord,string endWord,unordered_set<string>& wordList){  
            int result = INT_MAX;  
              
            if(beginWord == endWord)  
                return 1;  
            if(wordList.empty())  
                return INT_MAX;  
            int num = beginWord.size();  
            for(int i=0;i<num;i++)  
            {  
                string newWord = beginWord;
                for(char j='a';j<='z';j++)  
                {  
                    if(j == beginWord[i])  
                        continue;  
                    newWord[i] = j;  
                    if(wordList.count(newWord))  
                    {  
                        wordList.erase(newWord );  
                        int retemp = Tran(newWord,endWord,wordList);  
                        if(retemp != INT_MAX)  
                        {  
                            result = min(result,retemp+1);  
                        }  
                        wordList.insert(beginWord);                   
                    }  
                }  
            }  
            return result;  
              
        }  
    };  

DFS不行,会运行超时,那么就要采取更好的方法。只需要找到第一次出现endword的情况就好,可以通过BFS来记录当前层次可能出现的单词,如果出现了endword,那么该层次就是最小变换次数。实现的时候依然发生了时间超时,后面想了一想,在进行判断某个单次是否在词表里的时候需要时间复杂度O(N),可否降低该行为的时间复杂度呢?当然是可以的,通过hash函数可以将该过程的时间复杂度降为常数级。

代码如下:

class Solution {
public:
    int ladderLength(string beginWord, string endWord, vector<string>& dict) {
        unordered_set<string> wordList;
        for(int i=0;i<dict.size();i++)
            wordList.insert(dict[i]);
        if(beginWord.size() != endWord.size())
            return 0;
        if(beginWord.empty() || endWord.empty() || wordList.empty())
            return 0;
        int len = beginWord.size();
        
        int result = 1;
        deque<string> level;
        level.push_back(beginWord);
        while(!level.empty() && !wordList.empty())
        {
            int num = level.size();
            for(int i =0;i<num;i++)
            {
                string word = level.front();
                level.pop_front(); 
                for(int j=0;j<len;j++)
                {
                    string curr = word;
                    for(char k='a';k<='z';k++)
                    {
                        if(curr[j] == k)
                            continue;
                        curr[j] = k;
                        if(curr == endWord)
                                return result+1;
                        if(wordList.count(curr))
                        {
                            level.push_back(curr);   
                            wordList.erase(curr);
                        }
                    }
                }
            }
            result++;
        }
        return 0;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值