Bi-BFS

双向BFS算法,适用于起点和终点都给定的情况,求最短路径,即两个Set首次相交的情况

经典题目:Word ladder

  • 用两个set, beginSet and endSet

  • 不需要Queue

  • 每次确保 beginSet.size() < endSet.size()

  • 然后iterate element in beginSet to find neighbors

class Solution {
    public int ladderLength(String beginWord, String endWord, List<String> wordList) {
        //beginSet, endSet, tmpSet, visitedSet
        //fetch smaller set from beginSet and endSet, then check each of word in the set to see whether it's in wordList
        //if not, then add all unvisited neighbors to set
        Set<String> beginSet = new HashSet<>();
        beginSet.add(beginWord);
        Set<String> endSet = new HashSet<>();
        endSet.add(endWord);

        Set<String> visited = new HashSet<>();
        int len = 1;

        Set<String> wordSet = convertToSet(wordList);

        while (!beginSet.isEmpty() && !endSet.isEmpty()) {
            if (endSet.size() < beginSet.size()) {
                swap(beginSet, endSet);
            }
            Set<String> tmp = new HashSet<>();
            for (String cur : beginSet) {
                //get list of next words of cur from wordList
                List<String> nextWords = getNextWords(cur, wordSet, visited);
                for (String nextWord : nextWords) {
                    if (nextWord.equals(endWord)) {
                        return len + 1;
                    }
                    visited.add(nextWord);
                    tmp.add(nextWord);
                }
            }
            beginSet = tmp;
            len++;
        }
        return 0;
    }

    private Set<String> convertToSet(List<String> wordList) {
        Set<String> wordSet = new HashSet<>();
        for (String word : wordList) {
            wordSet.add(word);
        }
        return wordSet;
    }

    private void swap(Set<String> beginSet, Set<String> endSet) {
        Set<String> tmp = beginSet;
        beginSet = endSet;
        endSet = tmp;
    }

    private List<String> getNextWords(String curWord, Set<String> dict, Set<String> visited) {
        List<String> res = new ArrayList<>();
        for (char c = 'a'; c <= 'z'; c++) {
            for (int i = 0; i < curWord.length(); i++) {
                if (curWord.charAt(i) == c) {
                    continue;
                }
                String newWord = replace(curWord, i, c);
                if (!visited.contains(newWord) && dict.contains(newWord)) {
                    res.add(newWord);
                }
            }
        }
        return res;
    }

    private String replace(String word, int index, char c) {
        char[] charArr = word.toCharArray();
        charArr[index] = c;
        return new String(charArr);
    }
}

Last updated

Was this helpful?