• 字符串的转换路径问题


    问题描述

            给定两个字符串,记为start和to,再给定一个字符串列表list,list中一定包含to list中没有重复字符串,所有的字符串都是小写的。
            规定: start每次只能改变一个字符,最终的目标是彻底变成to,但是每次变成的新字符串必须在list 中存在。
            请返回所有最短的变换路径。
    【举例】
            start="abc",end="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

     思路

    思路一:

            我们建立一个邻居表,邻居的定义是:一个字符串通过改变一个字符就可以变成另一个字符串,那么另一个字符串就是这个字符的邻居。我们遍历每一个字符串查看后面的字符是否是当前字符串的邻居,即可得到我们需要的邻居表。邻居表的建立需要的时间复杂度为:O(N^2),我们在遍历当前的字符串就可以得到本题答案,算法的整体时间复杂度为:O(N^2*K),其中K表示字符串的长度。

    思路二:

            同样建立邻居表,不过同思路以不同的。我们把给定的字符串列表list全部放在一个hashmap中,由于本题中通过hashmap查找指定字符串时不能忽略字符串的长度,所以查找字符串的时间复杂度由原来的O(1)转变为O(K)。根据题目我们知道所有的字符串都是小写的所以每个字符的变化只有24种,我们列出开始字符串邻居的所有可能性(时间复杂度为:O(25*k)),在hashmap中查看是否有这种情况的邻居即可。整体的时间复杂度为O(K^2)。

            我们还需要建立距离表,其含义是该字符串到开始字符串的距离是多少。

    • 我们可以提前预处理出 start 和 list 中的每个字符串变换后的可能的下一个字符串,并根据这个建图
    • BFS 找出 start 到 to 的最短路径(注意:找到最短路径不要提前退出,需要把所有状态都处理掉,后面会用到)
    • 根据第二步的结果和状态之间的距离关系,DFS 搜索路径(重要:根据第二步的状态可大大减少搜索状态)
    • 将路径变换成字符串,并按照字典序从小到大排序并输出 

    代码

            这里我们演示思路二的代码 

    1. public static List> findMinPaths(String start, String end, List list) {
    2. list.add(start);
    3. HashMap> nexts = getNexts(list);
    4. HashMap distances = getDistances(start, nexts);
    5. LinkedList pathList = new LinkedList<>();
    6. List> res = new ArrayList<>();
    7. getShortestPaths(start, end, nexts, distances, pathList, res);
    8. return res;
    9. }
    10. public static HashMap> getNexts(List words) {
    11. Set dict = new HashSet<>(words);
    12. HashMap> nexts = new HashMap<>();
    13. for (int i = 0; i < words.size(); i++) {
    14. nexts.put(words.get(i), getNext(words.get(i), dict));
    15. }
    16. return nexts;
    17. }
    18. public static ArrayList getNext(String word, Set dict) {
    19. ArrayList res = new ArrayList<>();
    20. char[] chs = word.toCharArray();
    21. for (char cur = 'a'; cur <= 'z'; cur++) {
    22. for (int i = 0; i < chs.length; i++) {
    23. if (chs[i] != cur) {
    24. char tmp = chs[i];
    25. chs[i] = cur;
    26. if (dict.contains(String.valueOf(chs))) {
    27. res.add(String.valueOf(chs));
    28. }
    29. chs[i] = tmp;
    30. }
    31. }
    32. }
    33. return res;
    34. }
    35. public static HashMap getDistances(String start,
    36. HashMap
    37. ArrayList> nexts) {
    38. HashMap distances = new HashMap<>();
    39. distances.put(start, 0);
    40. Queue queue = new LinkedList<>();
    41. queue.add(start);
    42. HashSet set = new HashSet<>();
    43. set.add(start);
    44. while (!queue.isEmpty()) {
    45. String cur = queue.poll();
    46. for (String next : nexts.get(cur)) {
    47. if (!set.contains(next)) {
    48. distances.put(next, distances.get(cur) + 1);
    49. queue.add(next);
    50. set.add(next);
    51. }
    52. }
    53. }
    54. return distances;
    55. }
    56. private static void getShortestPaths(String cur, String to,
    57. HashMap> nexts,
    58. HashMap distances,
    59. LinkedList path,
    60. List> res) {
    61. path.add(cur);
    62. if (to.equals(cur)) {
    63. res.add(new LinkedList(path));
    64. } else {
    65. for (String next : nexts.get(cur)) {
    66. if (distances.get(next) == distances.get(cur) + 1) {
    67. getShortestPaths(next, to, nexts, distances, path, res);
    68. }
    69. }
    70. }
    71. path.pollLast();
    72. }
    73. public static void main(String[] args) {
    74. String start = "abc";
    75. String end = "cab";
    76. String[] test = {"cab", "acc", "cbc", "ccc", "cac", "cbb", "aab", "abb"};
    77. ArrayList list = new ArrayList<>();
    78. for (int i = 0; i < test.length; i++) {
    79. list.add(test[i]);
    80. }
    81. List> res = findMinPaths(start, end, list);
    82. System.out.println(res);
    83. }

  • 相关阅读:
    【个人记录 | 研二预答辩】
    python matplot画图攻略
    5081. 重复局面
    【论文导读】Learning Causal Semantic Representation forOut-of-Distribution Prediction
    【Element-plus】如何让滚动条永远在最底部(支持在线演示)
    Java SE 18 新增特性
    一天快速掌握Mybaits[一]
    新手入门案例学习,基于C# MVC实现汽修管理系统《建议收藏:附完整源码+数据库》
    基于鸽群优化算法的线性规划求解matlab程序
    动画详解常用排序算法(1)
  • 原文地址:https://blog.csdn.net/z1171127310/article/details/127869053