给定两个单词(beginWord 和 endWord)和一个字典,找到从 beginWord 到 endWord 的最短转换序列的长度。转换需遵循如下规则:
每次转换只能改变一个字母。
转换过程中的中间单词必须是字典中的单词。
说明:
如果不存在这样的转换序列,返回 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" 不在字典中,所以无法进行转换。
解析:
package com.leetcode.shuati;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
/**
* @Author: renyitian
* @Date: 4:11 下午 2020/11/5
* @Description:
* @Version v1.0
*/
public class BFS {
public static int ladderLength(String beginWord, String endWord, List<String> wordList) {
if (wordList == null || wordList.size() == 0) return 0;
//hashset的好处:去重也完成了
//开始端
HashSet<String> start = new HashSet<>();
//结束端
HashSet<String> end = new HashSet<>();
//所有字符串的字典
HashSet<String> dic = new HashSet<>(wordList);
start.add(beginWord);
end.add(endWord);
if (!dic.contains(endWord)) return 0;
//经历过上面的一系列判定,到这里的时候,若是有路径,则最小是2,所以以2开始
return getStepSize(start, end, dic, 2);
}
/**
* 1、修改begin的每一个字母 判断是否是符合要求或者在list中
* 2、如果和end相等说明知找到了 如果在list中而不再end中说明正在查找中 继续。。。
* 3、继续中可能存在多种在list存在的数据,每一个继续去找和end相等的 直到找到便是步长
*
* @param
* @Return
* @Date: 4:14 下午 2020/11/5
* @Author: renyitian
*/
public static int getStepSize(HashSet<String> begin, HashSet<String> end, HashSet<String> listString, int l) {
//出现断裂说明不存在
if (begin.size() == 0)
return 0;
if (begin.size() > end.size()) {//双端查找,为了优化时间,永远用少的去找多的,比如开始的时候塞进了1000个,而结尾只有3个,则肯定是从少的那一端开始走比较好
return getStepSize(end,begin, listString, l);
}
//已经使用过的数据不再做本次操作
listString.removeAll(begin);
//BFS收集变化之后的数据 继续查找end
HashSet<String> next = new HashSet<>();
//本次begin开始变化每一个字母 去找目标end
for (String str : begin) {
//遍历当前字符串查找符合list或者end字符串
char select[] = str.toCharArray();
for (int i = 0; i < select.length; i++) {
//可能变化的字符
char temp = select[i];
for (char j = 'a'; j <= 'z'; j++) {
//相同字母不改变
if (temp == j)
continue;
//当前不相等字母改变并判断是否是需要的数据
select[i] = j;
String nStr = new String(select);
//判断是否是需要的结果 如果是list而不是end说明变化ing
if (listString.contains(nStr)) {
if (end.contains(nStr))
return l;
else
next.add(nStr);
}
}
//复原
select[i] = temp;
}
}
//继续
return getStepSize(next, end, listString, l + 1);
}
public static void main(String[] args) {
String endWord ="oecij";
String beginWord = "ymain";
String wordList[] = {"ymann","yycrj","oecij","ymcnj","yzcrj","yycij","xecij","yecij","ymanj","yzcnj","ymain"};
List<String> list = Arrays.asList(wordList);
System.out.println(ladderLength(beginWord,endWord,list));
}
}
查看大佬的 一步步解析 大佬链接-》单词接龙