LeetCode_Word Ladder

原題:

Given two words (start and end), and a dictionary, find the length of shortest transformation sequence from start to end, such that:

  1. Only one letter can be changed at a time
  2. Each intermediate word must exist in the dictionary

For example,

Given:
start = "hit"
end = "cog"
dict = ["hot","dot","dog","lot","log"]

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.
題意是:給出兩個字符串start和end以及一個字符串集合dict,要求從start變換到end所需的最小步驟。變換規則是:每次只能改變字符串中的一個字符,而且改變後形成的新的字符串要是字典dict中的字符串。

剛看這題可能沒有思路,但是把變換過程在紙上畫畫之後就明白怎麼做了。以下是題目的抽象圖。


即從圖上找尋從起始節點到目標節點的最短路徑問題。這是圖的遍歷問題,使用的方法無非BFS和DFS,要找最短路徑,DFS只會一路到底,無疑BFS最合適。用BFS遍歷圖,一旦碰到目標節點即退出,此時路徑即是最短路徑。

注意:

(1)BFS搜索應該用隊列來模擬;

(2)應該用一個數組類型的數據結構來記錄已被遍歷的節點,爲求速度,可以使用unordered_set或set(竟然會超時可憐);

(3)遍歷時,應該將與某個節點相鄰的未訪問節點push進隊列中,但怎麼知道兩個節點相鄰?一個個搜索比較會超時,網上有一種很巧妙的方法,即依次將節點string的第i位變換(26次)然後在字典中查找變換後的節點是否在字典中(用的unordered_set數據結構,查找時間爲常數),相同的話push進隊列;

(4)節點不僅要記錄string,還要記錄其在遍歷中是第幾步,應該用一個struct封裝;

好了上代碼:

class Solution {
public:
	struct Node{
		string str;
		int count;
		Node(string s, int n) :str(s), count(n){}
	};
public:
	int ladderLength(string start, string end, unordered_set<string> &dict) 
	{
		if (start == end)
			return 1;
		if (isNeibours(start, end))
			return 2;
		visited.clear();
		while (!que.empty())
			que.pop();
		que.push(Node(start, 1));
		int res = 0;
		while (!que.empty())
		{
			Node NowNode(que.front());
			if (isNeibours(NowNode.str, end))
			{
				res = NowNode.count + 1;
				break;
			}
			que.pop();
			for (int i = 0; i < NowNode.str.size(); ++i)
			{
				for (int j = 0; j < 26; ++j)
				{
					string temp = NowNode.str;
					temp[i] = 'a' + j;
					if (temp != NowNode.str && dict.find(temp) != dict.end() && visited.find(temp) == visited.end())
					{
						que.push(Node(temp,NowNode.count+1));
						visited.insert(temp);
					}	
				}
			}
		}
		return res;
	}
private:
	bool isNeibours(string s1, string s2)
	{
		int count = 0;
		for (int i = 0; i < s1.size(); ++i)
		{
			if (s1[i] != s2[i])
				++count;
			if (count > 1)
				return false;
		}
		return true;
	}
private:
	unordered_set<string> visited;
	queue<Node> que;
};


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