Leetcode127: wordLadder I

Problem description

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.
    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.

Solution

递归法(暴力搜索):

#include <iostream>
#include <string>
#include <assert.h>
#include <vector>

using namespace std;

bool *isDealed;

bool isOneCharDiff(string s1, string s2)
{
    assert(s1.length() == s2.length());
    int cnt = 0;
    for (int i = 0; i < s1.length(); i++)
    {
        if (s1[i] != s2[i]) 
            cnt++;
    }

    if (cnt != 1)
        return false;
    return true;
}

void wordLadder(string beginWord, vector<string> &WordList, string endWord, int n, int depth, int *pL)
{
    if (beginWord == endWord)
    {
        if (*pL > depth)
            *pL = depth;
        return;
    }

    if (depth == n)
        return;

    for (int i = 0; i < n; i++)
    {
        if (!isDealed[i] && isOneCharDiff(WordList[i], beginWord))
        {
            isDealed[i] = true;
            wordLadder(WordList[i], WordList, endWord, n, depth + 1, pL);
            isDealed[i] = false;
        }
    }
}

int main()
{
    string beginWord, endWord;
    int n;
    cin >> beginWord >> endWord >> n;
    isDealed = new bool[n];
    vector<string> WordList(n);

    for (int i = 0; i < n; i++)
    {
        cin >> WordList[i];
        isDealed[i] = false;
    }

    int L = n + 1;
    wordLadder(beginWord, WordList, endWord, n, 0, &L);
    if (L < n + 1)
        cout << L << endl;
    else
        cout << 0 << endl;

    delete[] isDealed;
    return 0;
}

BFS法

#include <iostream>
#include <vector>
#include <set>
#include <string>
#include <queue>

using namespace std;

// one end bfs
/*class Solution { public: int ladderLength(string beginWord, string endWord, vector<string>& wordList) { set<string> wordSet(wordList.begin(), wordList.end()); char tmp; queue<string> Q; Q.push(beginWord); Q.push(""); //以空作为每一层的结束 int res = 1; while(!Q.empty()) { string str = Q.front(); Q.pop(); if (str != "") { for(int i = 0; i < str.length(); i++) { tmp = str[i]; for (char c = 'a'; c <= 'z'; c++) { if(str[i] == c) continue; str[i] = c; set<string>::iterator idx = wordSet.find(str); //vector<string>::iterator idx = find(wordList.begin(), wordList.end(), str); if (idx != wordSet.end()) { if (str == endWord) return res + 1; Q.push(str); wordSet.erase(idx); } } str[i] = tmp; } } else if (!Q.empty()) { res++; Q.push(""); } } return 0; } }; */

// two end bfs
class Solution {
public:
    int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
        set<string> wordSet(wordList.begin(), wordList.end());
        set<string> beginSet, endSet, *set1, *set2;
        beginSet.insert(beginWord);
        endSet.insert(endWord);
        int res = 1;

        if (wordSet.find(endWord) == wordSet.end())
            return 0;

        while (!beginSet.empty() && !endSet.empty())
        {
            if (beginSet.size() <= endSet.size())
            {
                set1 = &beginSet;
                set2 = &endSet;
            }
            else
            {
                set1 = &endSet;
                set2 = &beginSet;
            }
            set<string> itemSet;
            set<string>::iterator i;
            for (i = set1->begin(); i != set1->end(); i++)
            {
                string str = *i;
                for (int i = 0; i < str.length(); i++)
                {
                    char tmp = str[i];
                    for (char c = 'a'; c <= 'z'; c++)
                    {
                        if (str[i] == c) continue;
                        str[i] = c;
                        set<string>::iterator j = set2->find(str);
                        if (j != set2->end()) 
                            return res + 1;
                        set<string>::iterator idx = wordSet.find(str);
                        if (idx != wordSet.end())
                        {   
                            itemSet.insert(str);
                            wordSet.erase(idx);
                        }
                    }
                    str[i] = tmp;
                }
            }
            swap(*set1, itemSet);
            res++;
        }
        return 0;
    }
};

int main()
{
    string str_array[] ={"hot","dot","dog","lot","log","cog"}; //以这个序列为例
    string begin = "hit";
    string end = "cog";
    vector<string> wordList(str_array, str_array + 6);
    Solution s;
    cout << s.ladderLength(begin, end, wordList) << endl;
    return 0;
}

link:

  1. https://leetcode.com/discuss/28573/share-my-two-end-bfs-in-c-80ms
  2. http://www.cnblogs.com/TenosDoIt/p/3443512.html
点赞