leetcode126--单词接龙II

题目链接:https://leetcode-cn.com/problems/word-ladder-ii/

题目描述:

给定两个单词(beginWord 和 endWord)和一个字典 wordList,找出所有从 beginWord 到 endWord 的最短转换序列。转换需遵循如下规则:


    每次转换只能改变一个字母。
    转换过程中的中间单词必须是字典中的单词。


说明:


    如果不存在这样的转换序列,返回一个空列表。
    所有单词具有相同的长度。
    所有单词只由小写字母组成。
    字典中不存在重复的单词。
    你可以假设 beginWord 和 endWord 是非空的,且二者不相同。


示例 1:

输入:
beginWord = "hit",
endWord = "cog",
wordList = ["hot","dot","dog","lot","log","cog"]

输出:
[
  ["hit","hot","dot","dog","cog"],
  ["hit","hot","lot","log","cog"]
]


示例 2:

输入:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log"]

输出: []

解释: endWord "cog" 不在字典中,所以不存在符合要求的转换序列。

题目分析:从一个单词转换到另一个单词经过的路径,由于中间经过转换的路径一定要在给定的wordlist中,并且每次变换只能更改一个单词,因此,我们可以把每个单词能够变换到的词,也可以理解为能达到的路径标记出来,题目又是要求最短路径,使用BFS可以求得,将每个单词理解为一个点,每个单词能变换的过程理解为路径,那么题目就转化为求在一个图中从一个点到另一个点的最短路径,综上,先建图,然后BFS遍历,由于要记录路径所经过的节点,我们借助map来存储单词的映射关系,方便输出

class Solution {
  HashMap<String,Integer> wordmap;//为每个单词生成ID,简化处理
  ArrayList<String> words ;//为了记录路径,用ID来获取单词
  ArrayList<Integer>[] edges;//边
  //判断2个单词能否相互转化
  public boolean isOk(String s1,String s2){
     int cnt = 0;
     for(int i = 0;i < s1.length();i++){
          if(s1.charAt(i)!=s2.charAt(i))
            cnt++;
     }
     return cnt == 1;
  }
  public List<List<String>> findLadders(String beginWord, String endWord, List<String> wordList) {
       wordmap = new HashMap<>();
       words = new ArrayList<>();
       int id = 0;
       for (String str : wordList) {//建立映射
          if(!wordmap.containsKey(str)){
            wordmap.put(str, id++);
            words.add(str);
          }
       }
       //不符合要求的情况
       if(!wordmap.containsKey(endWord)) return new ArrayList<>();
       if(!wordmap.containsKey(beginWord)){//将所有单词都建立映射
         wordmap.put(beginWord, id++);
         words.add(beginWord);
       }
        edges = new ArrayList[words.size()];
        for (int i = 0; i < words.size(); i++) {
            edges[i] = new ArrayList<>();
        }
        //建图
       for (int i = 0; i < words.size(); i++) {
         for (int j = i+1; j < words.size(); j++) {
            if(isOk(words.get(i), words.get(j))){//可以相互转化建立边
                 edges[i].add(j);
                 edges[j].add(i);
            }
         }
       }
       //cost数组代表beginWord到i为止所花费的转换代价(次数)
       int[] cost = new int[words.size()];
       Arrays.fill(cost, 1<<20);
       List<List<String>> res = new ArrayList<>();
       int des = wordmap.get(endWord);
       //初始化
       LinkedList<ArrayList<Integer>> q = new LinkedList<>();
       ArrayList<Integer> te = new ArrayList<>();
       te.add(wordmap.get(beginWord));
       q.add(te);
       cost[wordmap.get(beginWord)] = 0;
       //BFS求最短路径
       while(!q.isEmpty()){
         ArrayList<Integer> cur = q.poll();
         int to = cur.get(cur.size()-1);//路径的最后一个节点
         if(to == des){//达到了终点,加入res
           ArrayList<String> temp = new ArrayList<>();
           for (Integer index : cur) {
                 temp.add(words.get(index));
           }
           res.add(temp);
         }else{//继续遍历下一个可达的点
            for (int i = 0; i < edges[to].size(); i++) {
               int end = edges[to].get(i);
               if(cost[end]>=cost[to]+1){//如果代价更小,就加入路径,=代表可以相同长度的也是满足的
                 cost[end] = cost[to]+1;//更新代价
                 ArrayList<Integer> temp = new ArrayList<>(cur);
                  temp.add(end);
                  q.add(temp);
               }
            }
         }
       }
       return res;
  }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值