一、Problem
給出兩個單詞(開始單詞和結束單詞)以及一個詞典。找出從開始單詞轉換到結束單詞,所需要的最短轉換序列。轉換的規則如下:
- 每次只能改變一個字母
- 轉換過程中出現的單詞(除開始單詞和結束單詞)必須存在於詞典中
例如:
- 開始單詞爲:hit
結束單詞爲:cog
詞典爲:[hot,dot,dog,lot,log,mot]
那麼一種可能的最短變換是: hit -> hot -> dot -> dog -> cog,所以返回的結果是序列的長度5;
注意:
- 如果不能找到這種變換,則輸出0;
- 詞典中所有單詞長度一樣;
- 所有的單詞都由小寫字母構成;
- 開始單詞和結束單詞可以不在詞典中。
輸入
共兩行,第一行爲開始單詞和結束單詞(兩個單詞不同),以空格分開。第二行爲若干的單詞(各不相同),以空格分隔開來,表示詞典。單詞長度不超過5,單詞個數不超過30。
輸出
輸出轉換序列的長度。
樣例輸入
hit cog
hot dot dog lot log
樣例輸出
5
二、Solution
方法一:bfs
- 這本質是一道圖論問題,想象一下,每個單詞是一個結點,單詞之間的邊的邊權爲 1。
- 問題轉化爲求從結點 w1 到達 w2 的最短路徑。
- 如果判斷兩兩單詞的變換是否合法?
- 暴力匹配即可。
import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
static String w1, w2;
static Info[] all;
static int cnt;
static boolean valid(String s1, String s2) {
int diff = 0;
for (int i = 0; i < s1.length(); i++) {
if (s1.charAt(i) != s2.charAt(i))
diff++;
if (diff > 1)
return false;
}
return diff == 1;
}
static int bfs() {
Queue<Info> q = new LinkedList<>();
Info i = new Info();
i.s = w1; i.d = 1; i.vis = true;
q.add(i);
while (!q.isEmpty()) {
Info t = q.poll();
if (valid(t.s, w2)) {
return t.d + 1;
}
for (int k = 0; k < cnt; k++) {
if (all[k].vis || !valid(t.s, all[k].s))
continue;
Info info = new Info();
info.s = all[k].s;
info.vis = true;
info.d = t.d + 1;
q.add(info);
}
}
return 0;
}
public static void main(String[] args) throws IOException {
Scanner sc = new Scanner(new BufferedInputStream(System.in));
w1 = sc.next();
w2 = sc.next();
all = new Info[30 + 5];
for (int i = 0; i < all.length; i++)
all[i] = new Info();
while (sc.hasNext()) {
all[cnt].s = sc.next();
cnt++;
}
int res = bfs();
System.out.println(res);
}
static class Info {
String s;
boolean vis;
int d;
}
}
複雜度分析
- 時間複雜度:,
- 空間複雜度:,