Leetcode 127单词接龙

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/iov3Rain/article/details/88934320

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

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

说明:

  • 如果不存在这样的转换序列,返回 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" 不在字典中,所以无法进行转换。

用DFS和BFS都行,本题用BFS效率更高。

最开始想的是把每个单词能转成的单词用multimap记录下来。

然后再用BFS进行遍历,这样就减少了重复进行对比的次数。

但是如果单词多了起来后,效率就很低了。

class Solution
{
  public:
    int ladderLength(string beginWord, string endWord, vector<string> &wordList)
    {
        int n = beginWord.size();
        multimap<string, string> mm;
        for (int i = 0; i < wordList.size(); i++)
        {
            int cnt = 0;
            for (int k = 0; k < n; k++)
            {
                if(beginWord[k] != wordList[i][k])
                    cnt++;
            }
            if(cnt == 1)
            {
                mm.insert(make_pair(beginWord, wordList[i]));
                mm.insert(make_pair(wordList[i], beginWord));
            }
        }
        for (int i = 0; i < wordList.size(); i++)
        {
            for (int j = i + 1; j < wordList.size(); j++)
            {
                int cnt = 0;
                for (int k = 0; k < n; k++)
                {
                    if (wordList[i][k] != wordList[j][k])
                        cnt++;
                }
                if (cnt == 1)
                {
                    mm.insert(make_pair(wordList[i], wordList[j]));
                    mm.insert(make_pair(wordList[j], wordList[i]));
                }
            }
        }
        queue<string> q;
        q.push(beginWord);
        map<string, bool> visit;
        visit[beginWord] = true;
        int ans = 0;
        while(!q.empty())
        {
            int size = q.size();
            ans++;
            for (int i = 0; i < size; i++)
            {
                string temp = q.front();
                q.pop();
                multimap<string, string>::iterator beg, end, it;
                beg = mm.lower_bound(temp);
                end = mm.upper_bound(temp);
                for (it = beg; it != end; it++)
                {
                    if((*it).second == endWord)
                    {
                        return ans + 1;
                    }
                    if (!visit[(*it).second])
                    {
                        visit[(*it).second] = true;
                        q.push((*it).second);
                    }
                }
            }
        }
        return 0;
    }
};

优化1:倒着搜索比正着搜索效率更高,因为倒着搜索无效的结果比正着的少很多。

class Solution
{
  public:
    int ladderLength(string beginWord, string endWord, vector<string> &wordList)
    {
        int n = beginWord.size();
        multimap<string, string> mm;
        for (int i = 0; i < wordList.size(); i++)
        {
            int cnt = 0;
            for (int k = 0; k < n; k++)
            {
                if(beginWord[k] != wordList[i][k])
                    cnt++;
            }
            if(cnt == 1)
            {
                mm.insert(make_pair(beginWord, wordList[i]));
                mm.insert(make_pair(wordList[i], beginWord));
            }
        }
        for (int i = 0; i < wordList.size(); i++)
        {
            for (int j = i + 1; j < wordList.size(); j++)
            {
                int cnt = 0;
                for (int k = 0; k < n; k++)
                {
                    if (wordList[i][k] != wordList[j][k])
                        cnt++;
                }
                if (cnt == 1)
                {
                    mm.insert(make_pair(wordList[i], wordList[j]));
                    mm.insert(make_pair(wordList[j], wordList[i]));
                }
            }
        }
        queue<string> q;
        q.push(endWord);
        map<string, bool> visit;
        visit[endWord] = true;
        int ans = 0;
        while(!q.empty())
        {
            int size = q.size();
            ans++;
            for (int i = 0; i < size; i++)
            {
                string temp = q.front();
                q.pop();
                multimap<string, string>::iterator beg, end, it;
                beg = mm.lower_bound(temp);
                end = mm.upper_bound(temp);
                for (it = beg; it != end; it++)
                {
                    if((*it).second == beginWord)
                    {
                        return ans + 1;
                    }
                    if (!visit[(*it).second])
                    {
                        visit[(*it).second] = true;
                        q.push((*it).second);
                    }
                }
            }
        }
        return 0;
    }
};

优化2:

因为只有小写字母,字母只有26个,所以用在每个位置进行字母的变化,再用上set的高效率查找。

每次查找的复杂度为,字符串长度 * 26 * set.find()

倒着查找,效率更高。

class Solution
{
  public:
    int ladderLength(string beginWord, string endWord, vector<string> &wordList)
    {
        //查是否已经遍历过
        unordered_map<string, bool> visit;
        //增加查询速度
        unordered_set<string> words(wordList.begin(), wordList.end());
        if(words.find(endWord) == words.end())
            return 0;
        int ans = 0;
        queue<string> q;
        visit[endWord] = true;
        q.push(endWord);
        while(!q.empty())
        {
            int size = q.size();
            ++ans;
            while(size--)
            {
                string front = q.front();
                q.pop();
                for (int i = 0; i < front.size(); i++)
                {
                    string temp = front;
                    for (char j = 'a'; j <= 'z'; j++)
                    {
                        if(front[i] == j)
                            continue;
                        front[i] = j;
                        if(front == beginWord)
                            return ans + 1;
                        if(words.find(front) != words.end() && !visit[front])
                        {
                            visit[front] = true;
                            q.push(front);
                        }
                    }
                    front = temp;
                }
            }
        }
        return 0;
    }
};

猜你喜欢

转载自blog.csdn.net/iov3Rain/article/details/88934320