單詞接龍

題目描述

給定兩個單詞(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" 不在字典中,所以無法進行轉換。

思路

兩端搜索。本題是需要從beginWord轉換爲endWord。上一份筆記嚴格按照這個要求,進行轉換,結果爲88ms

本條筆記採用兩端搜索對上一份筆記進行了優化。兩端搜索也就是說:“一頭從beginWord轉換爲endWord,另外一頭從endWord轉換爲beginWord。”爲什麼要這麼做呢?有什麼意義呢?

舉個例子:

  • 假設從beginWord轉換爲endWord,存在於字典中的,(第一個)中間結果有30個。

  • 而,從endWord轉換爲beginWord,存在於字典中的,(第一個)中間結果只有2個。

  • 那麼,很顯然。從endWord開始會更快。所以,每次都從個數少的那塊開始替換一位。

因此,我們每次都從中間結果少的那一端出發,這樣就能剪枝掉很多不必要的搜索過程。

實現1

bool isOneChar(string& word1, string& word2) {
	if (word1.length() != word2.length())
	{
		return false;
	}

	int count = 0;
	int len = word1.length();
	for (int i = 0; i < len; i++)
	{
		if (word1[i] != word2[i])
		{
			count++;
		}
	}

	return count == 1;
}

void getResultWord(string beginWord, string endWord, vector<string>& wordList, vector<string>& vecList, int& minLen){

	if (beginWord == endWord)
	{
		if (vecList.size() < minLen)
		{
			minLen = vecList.size();
		}
	} else if (isOneChar(beginWord, endWord))
	{
		vecList.push_back(endWord);
		if (vecList.size() < minLen)
		{
			minLen = vecList.size();
		}
	} else {

		int startCount = 0;
		int endCount = 0;

		for (int i = 0; i < wordList.size(); i++)
		{
			if (find(vecList.begin(), vecList.end(), wordList[i]) == vecList.end())
			{
				if(isOneChar(beginWord, wordList[i])) {
					startCount++;
				}
				if (isOneChar(endWord, wordList[i]))
				{
					endCount++;
				}
			}
		}

		if (startCount <= endCount)
		{
			for (int i = 0; i < wordList.size(); i++)
			{
				if (find(vecList.begin(), vecList.end(), wordList[i]) == vecList.end() && isOneChar(beginWord, wordList[i])) {
					vecList.push_back(wordList[i]);
					getResultWord(wordList[i], endWord, wordList, vecList, minLen);
					vecList.pop_back();
				}
			}
		} else {
			for (int i = 0; i < wordList.size(); i++)
			{
				if (find(vecList.begin(), vecList.end(), wordList[i]) == vecList.end() && isOneChar(endWord, wordList[i])) {
					vecList.push_back(endWord);
					getResultWord(beginWord, wordList[i], wordList, vecList, minLen);
					vecList.pop_back();
				}
			}
		}


		
	}
}


int ladderLength(string beginWord, string endWord, vector<string>& wordList) {

	if (find(wordList.begin(), wordList.end(), endWord) == wordList.end())
	{
		return 0;
	}

	vector<string> vecList;
	int minLen = INT_MAX;
	vecList.push_back(beginWord);
	getResultWord(beginWord, endWord, wordList, vecList, minLen);

	if (minLen == INT_MAX)
	{
		minLen = 0;
	}

	return minLen;
}

 實現2

int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
    unordered_set<string> wordDict(wordList.begin(), wordList.end());
    if (wordDict.find(endWord) == wordDict.end()){
        return 0;
    }
    unordered_set<string> beginSet{beginWord};
    unordered_set<string> endSet{endWord};
    int step = 1;
    for (; !beginSet.empty();){
        unordered_set<string> tempSet;
        ++step;
        for (auto s : beginSet) {
            wordDict.erase(s);
        }
        for (auto s : beginSet) {
            for (int i = 0; i < s.size(); ++i){
                string str = s;
                for (char c = 'a'; c <= 'z'; ++c){
                    str[i] = c;
                    if (wordDict.find(str) == wordDict.end()){
                        continue;
                    }
                    if (endSet.find(str) != endSet.end()){
                        return step;
                    }
                    tempSet.insert(str);
                }
            }
        }
        if (tempSet.size() < endSet.size()){
            beginSet = tempSet;
        } else {
            beginSet = endSet;
            endSet = tempSet;
        }
    }
    return 0;
}

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章