每日一题 为了工作 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());
        }
    }
}

  

*运行结果

 

 

posted @ 2020-04-20 13:37  雪瞳  阅读(253)  评论(0编辑  收藏  举报