LeetCode 126. Word Ladder II(单词梯子)

21 篇文章 0 订阅
17 篇文章 0 订阅

原题网址:https://leetcode.com/problems/word-ladder-ii/

Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transformation sequence(s) from beginWord to endWord, such that:

  1. Only one letter can be changed at a time
  2. Each intermediate word must exist in the word list

For example,

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

Return

  [
    ["hit","hot","dot","dog","cog"],
    ["hit","hot","lot","log","cog"]
  ]

Note:

  • All words have the same length.
  • All words contain only lowercase alphabetic characters.

方法一:广度优先搜索,递推实现。

public class Solution {
    public List<List<String>> findLadders(String beginWord, String endWord, Set<String> wordList) {
        List<List<String>> ladders = new ArrayList<>();
        Map<String, List<String>> maskedWords = new HashMap<>();
        wordList.add(beginWord);
        wordList.add(endWord);
        for(String word: wordList) {
            char[] wa = word.toCharArray();
            for(int i=0; i<wa.length; i++) {
                char ch = wa[i];
                wa[i] = '*';
                String mask = new String(wa);
                wa[i] = ch;
                List<String> words = maskedWords.get(mask);
                if (words == null) {
                    words = new ArrayList<>();
                    maskedWords.put(mask, words);
                }
                words.add(word);
            }
        }
        wordList.remove(beginWord);
        List<Ladder> currents = new ArrayList<>();
        currents.add(new Ladder(beginWord, null));
        int from = 0;
        int to = 1;
        BFS: while (from < currents.size()) {
            to = currents.size();
            for(int i=from; i<to; i++) {
                String word = currents.get(i).word;
                if (word.equals(endWord)) {
                    break BFS;
                }
                char[] wa = word.toCharArray();
                for(int j=0; j<wa.length; j++) {
                    char ch = wa[j];
                    wa[j] = '*';
                    String mask = new String(wa);
                    wa[j] = ch;
                    List<String> words = maskedWords.get(mask);
                    for(String w: words) {
                        if (wordList.contains(w)) {
                            currents.add(new Ladder(w, currents.get(i)));
                        }
                    }
                }
            }
            from = to;
            for(int i=to; i<currents.size(); i++) {
                wordList.remove(currents.get(i).word);
            }
        }
        if (from < currents.size()) {
            for(int i=from; i<to; i++) {
                String word = currents.get(i).word;
                if (!word.equals(endWord)) continue;
                LinkedList<String> ladder = new LinkedList<>();
                Ladder l = currents.get(i);
                do {
                    ladder.addFirst(l.word);
                    l = l.prev;
                } while (l != null);
                ladders.add(ladder);
            }
        }
        return ladders;
    }
}
class Ladder {
    String word;
    Ladder prev;
    Ladder(String word, Ladder prev) {
        this.word = word;
        this.prev = prev;
    }
}

方法二:广度优先搜索,关键是搜索完整一层之后,再删除相关节点。

public class Solution {
    private List<List<String>> find(List<Ladder> ladders, String endWord, Set<String> wordList) {
        List<List<String>> results = new ArrayList<>();
        for(Ladder ladder : ladders) {
            if (ladder.word.equals(endWord)) {
                List<String> result = new ArrayList<>();
                while (ladder != null) {
                    result.add(0, ladder.word);
                    ladder = ladder.prev;
                }
                results.add(result);
            }
        }
        if (!results.isEmpty()) return results;
        
        List<Ladder> nexts = new ArrayList<>();
        for(Ladder ladder : ladders) {
            char[] la = ladder.word.toCharArray();
            for(int i=0; i<la.length; i++) {
                char origin = la[i];
                for(char ch = 'a'; ch <= 'z'; ch ++) {
                    if (ch == origin) continue;
                    la[i] = ch;
                    String s = new String(la);
                    if (wordList.contains(s)) nexts.add(new Ladder(s, ladder));
                }
                la[i] = origin;
            }
        }
        if (nexts.isEmpty()) return new ArrayList<>();
        for(Ladder ladder : nexts) wordList.remove(ladder.word);
        return find(nexts, endWord, wordList);
    }
    public List<List<String>> findLadders(String beginWord, String endWord, Set<String> wordList) {
        wordList.remove(beginWord);
        List<Ladder> ladders = new ArrayList<>();
        ladders.add(new Ladder(beginWord, null));
        return find(ladders, endWord, wordList);
    }
}
class Ladder {
    String word;
    Ladder prev;
    Ladder(String word, Ladder prev) {
        this.word = word;
        this.prev = prev;
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值