每日一题 为了工作 2020 0420 第四十九题
/**
*
* 【问题】字符串转换路径问题
* 给定两个字符串,记为start和to,再给定一个字符串列表list,list中一定包含
* to,list中没有重复的字符串。所有字符串都是小写的。规定start每次只可以改
* 变一个字符,最终的目标是彻底变成to,但每次变成的字符串都必须在list中存在。
* 请返回最短的变换路径。
* 【举例】
* start = "abc"
* to = "cab"
* list = {"cab","acc","cbc","ccc","cac","cbb","aab","abb"}
* 转换路径的方法有很多种,但是最短的转换路径如下:
* abc --> abb --> aab --> cab
* abc --> abb --> cbb --> cab
* abc --> cbc --> cac --> cab
* abc --> cbc --> cbb --> cab
* 【分析】
* 本题目难度较大,需要拆分成四个步骤进行实现,接下来完成第一步骤获取每一个
* 字符串的nexts信息。
*
* 【第一步】
* 将start加入list,然后根据list生成每一个字符串的nexts信息。nexts具体是
* 指如果朱改变一个字符,该字符串可以变成哪些字符串。比如上面的list,先把
* "abc"加入到list中,然后根据list生成信息如下:
* 字符串 nexts信息(next要求属于list 否则丢弃)
* acc abc ccc
* abb aab cbb abc
* ccc acc cac cbc
* cbb abb cab cbc
* abc abb cbc acc
* aab abb cab
* cac cbc cab ccc
* cab aab cbb cac
* cbc abc cac cbb ccc
*
* 如何判断生成的一个字符串是否在list内呢?
* 首先把list中所有的字符串放入哈希表set中,这样检查某一个字符串是否在list中
* 就可以通过查询set来实现,这样做的原因是哈希表查询的时间复杂度是O(1),比遍
* 历list查询某个字符串是否在其中速度要快很多。
*
* 如何生成字符串的nexts信息呢?
* 因为每一个字符都是小写,所以看"bcc" "ccc" "dcc" "ecc" ..."zcc"哪些在set中,
* 就把哪些放到"acc"的nexts列表中;然后看"aac" "abc" "adc" "aec" ... "azc"哪些
* 在set中,就把哪些放到"acc"的nexts列表中;最后看"aca" "acb" "acd" ... "acz"
* 哪些在set中,就把哪些放到"acc"的nexts列表中。也就是说,某个位置的字符都是从
* a --> z 开始枚举,哪些在set中就放到该元素的nexts列表中。
*
* @author 雪瞳
* @Slogan 时钟尚且前行,人怎能再次止步!
* @Function 返回没一个字符串的next信息
*
*/
public class GetNexts {
public HashMap<String,ArrayList<String>> getNexts(List<String> words){
//将list放入哈希表内
Set<String> dict =new HashSet<>(words);
HashMap<String,ArrayList<String>> nexts = new HashMap<>();
for (int i=0;i<words.size();i++){
//给每一个元素创建一个nexts的kv映射 k为当前元素 v为该元素变换后的列表
//列表初始为空
nexts.put(words.get(i),new ArrayList<>());
}
for (int i=0;i<words.size();i++){
//向列表内添加元素
nexts.put(words.get(i),getNext(words.get(i),dict));
}
return nexts;
}
public ArrayList<String> getNext(String word, Set<String> dict){
ArrayList<String> res = new ArrayList<>();
//将每一个位置元素拆分成字符
char[] chs = word.toCharArray();
//对每一个位置都有26中字符改变
for ( char cur = 'a'; cur <= 'z';cur++){
for (int i=0;i<chs.length;i++){
//当前字符可以进行转换
if (chs[i] != cur){
char tmp = chs[i];
chs[i] = cur;
//判断转换后的字符串是否在哈希表中
if (dict.contains(String.valueOf(chs))){
res.add(String.valueOf(chs));
}
//将字符串复原 进行下一个位置的变换
chs[i]=tmp;
}
}
}
return res;
}
public static void main(String[] args) {
List<String> list = new ArrayList<>();
String[] elements = new String[]{"cab","acc","cbc","ccc","cac","cbb","aab","abb"};
for (String elem : elements){
list.add(elem);
}
GetNexts get = new GetNexts();
HashMap<String, ArrayList<String>> nexts = get.getNexts(list);
Set<Map.Entry<String, ArrayList<String>>> entries = nexts.entrySet();
for (Map.Entry<String, ArrayList<String>> entry : entries){
System.out.println(entry.getKey()+"----"+entry.getValue());
}
}
}
*运行结果