Word Ladder
Given two words (start and end), and a dictionary, find the length of shortest transformation sequence from start to end, such that:
- Only one letter can be changed at a time
- 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.
分析:
1. 一開始覺得,hit 變到 cog,肯定是每次變化一個單詞,距離len+1。只要判斷每一種變化的可能是否在dict中即可。 忽略了字典中很多詞可以作爲中間狀態,例如dog就與hit沒有任何字母相同。
2. Google之,BST,廣度優先遍歷。start到end可以看做是 點到點的一條路徑,而每變化一個單詞可以看做是路徑+1。
如例子中,hit作爲第一層,第二層則是((a-z)it ∩ dict)∪(h(a-z)t ∩ dict) ∪(hi(a-z) ∩ dict)然後除去hit本身。注意end(即cog不需要在詞典中)依次往下推,如果發現了end,則直接返回當前的distance即可。因爲是層序遍歷,所以當前路徑保證是最小的。
注意:
1. 層序遍歷用queue,每層過渡節點push到隊列中後,對應的dict中的單詞要刪掉。因爲不刪掉會進入死循環,如hit -> hot->lot -> hot 每次改變一個單詞,會變成它的前一個節點。
2. 每層的分界線,用""
代碼:
class Solution {
public:
int ladderLength(string start, string end, unordered_set<string> &dict) {//BFS 最短路徑問題
if(start==end) return 0;
int len=start.size();
queue<string> qu;
qu.push(start);
qu.push("");//標記每一層
int distance=1;
while(qu.size()>1 && dict.size()>0){//每層循環
//distance++;
while(qu.front()!="" && dict.size()>0){//每層內一個個元素的循環
string tmp=qu.front();
qu.pop();
for(int i=0;i<len;i++){
string pusht=tmp;
for(char t='a';t<='z';t++){//a-z依次試探,看是否在dict中
if(pusht[i]==t) continue;//tmp本身
pusht[i]=t;
if(pusht==end) return distance+1;//找到了 便是最短的 層序遍歷
unordered_set<string>::const_iterator it=dict.find(pusht);
if(it!=dict.end()){//字典中有這個單詞
qu.push(pusht);
dict.erase(it);//刪除字典中對應的值
}
}//for t
}//for i
}//while
qu.pop();//刪除""
if(qu.empty()) return 0;
else distance++;
qu.push("");
} //層while
return 0;
}
};