DFS、双向BFS 127.单词接龙


127.单词接龙

在这里插入图片描述
DFS(超时)

    /**
     * 算法一:暴力回溯
     * 超时!!
     * */

    /**
     *
     * @param beginWord:src 字符串
     * @param endWord:des 字符串
     * @param wordList:字典
     * @return 转换序列长度,即转换次数+1
     */
    static boolean[] isVisited;
    public static int ladderLength(String beginWord, String endWord, List<String> wordList) {
        if (wordList == null || wordList.size() == 0 || !wordList.contains(endWord)) return 0;
        isVisited = new boolean[wordList.size()+1];
        int ans = dfs(beginWord,endWord,wordList);
        return ans == Integer.MAX_VALUE ? 0 : ans;
    }

    private static int dfs(String beginWord,String endWord,List<String> wordList){
        if (endWord.equals(beginWord))
            return 1;

        Map<String, Integer> map = withOneDifferent(beginWord, wordList);
        int min = Integer.MAX_VALUE;
        Iterator<String> iterator = map.keySet().iterator();
        int cnt;
        while (iterator.hasNext()){
            String next = iterator.next();
            isVisited[map.get(next)] = true;
            cnt = dfs(next,endWord,wordList);
            min = Math.min(min,cnt);
            isVisited[map.get(next)] = false;
        }

        return min == Integer.MAX_VALUE ? Integer.MAX_VALUE : min+1;
    }
    /**
     * 返回与str只有一个字母不同的单词列表
     */
    private static Map<String,Integer> withOneDifferent(String str,List<String> wordList){
        Map<String,Integer> map = new HashMap<>();
        int n = wordList.get(0).length();
        int l,r;
        int index = 0;
        for (String s : wordList){
            if (isVisited[index++] || s.equals(str))
                continue;

            l = 0;
            r = n-1;
            while (l < n && s.charAt(l) == str.charAt(l))
                l++;
            while (r > l && s.charAt(r) == str.charAt(r))
                r--;

            if (l == r && s.charAt(l) != str.charAt(l))
                map.put(s,index-1);
        }
        return map;
    }

双向BFS

/**
* 双向bfs
*/
static Map<String,List<String>> match = new HashMap<>();
public static int ladderLength2(String beginWord, String endWord, List<String> wordList) {
   if (!wordList.contains(endWord))
       return 0;

   int n = wordList.get(0).length();
   //预处理

   wordList.forEach(word ->{
       for (int i = 0; i < n; i++) {
           String state = word.substring(0,i)+"*"+word.substring(i+1,n);
           List<String> list = match.getOrDefault(state, new ArrayList<>());
           list.add(word);
           match.put(state,list);
       }
   });

   //双向dfs
   Queue<Pair<String,Integer>> queueBeg = new LinkedList<>();
   Queue<Pair<String,Integer>> queueEnd = new LinkedList<>();
   queueBeg.offer(new Pair<>(beginWord,1));
   queueEnd.offer(new Pair<>(endWord,1));

   Map<String,Integer> isVisitBeg = new HashMap<>();
   Map<String,Integer> isVisitEnd = new HashMap<>();
   isVisitBeg.put(beginWord,1);
   isVisitEnd.put(endWord,1);

   int ans = 0;
   while (!queueBeg.isEmpty() && !queueEnd.isEmpty()){
       ans = bfs(queueBeg,isVisitBeg,isVisitEnd);
       if (ans != -1)
           return ans;

       ans = bfs(queueEnd,isVisitEnd,isVisitBeg);
       if (ans != -1)
           return ans;
   }
   return 0;
}

/**
* 也就是,当双向dfs访问同一个节点时,说明找到了最短的路径
* @param queue: 队列
* @param isVisited:当前队列访问过的节点
* @param othersVisited:另一个方向的bfs所访问过的节点
* @return
*/
private static int bfs(Queue<Pair<String,Integer>> queue,Map<String,Integer> isVisited,Map<String,Integer> othersVisited){
   Pair<String, Integer> pair = queue.remove();
   String word = pair.getKey();
   Integer floor = pair.getValue();

   for (int i = 0; i < word.length(); i++) {
       String state = word.substring(0,i)+"*"+word.substring(i+1,word.length());
       List<String> list = match.getOrDefault(state, new ArrayList<>());

       for (String adj : list){
           if (othersVisited.containsKey(adj)){
               return othersVisited.get(adj) + floor;
           }else if (!isVisited.containsKey(adj)){
               isVisited.put(adj,floor+1);
               queue.add(new Pair<>(adj,floor+1));
           }
       }
   }
   return -1;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值