Word Ladder I&&II (Snapchat)

2016-11-23 晚上 Bobst

这两道题乍一看是String的题,其实是隐式图的搜索问题,每个单词是一个节点,相邻的单词是边。

既然是求最短的变换距离,那么肯定是用BFS来做比较方便。也就是用BFS求两点之间的最短距离问题。

Word Ladder I

一个比较标准的BFS解法

public class Solution {
    public int ladderLength(String beginWord, String endWord, Set<String> wordList) {
        if(beginWord ==null || endWord==null || beginWord.length()==0 ||
         endWord.length()==0 || beginWord.length()!=endWord.length())  
            return 0;  

        // bfs, find the adjacent word
        wordList.add(beginWord);
        wordList.add(endWord);

        Queue<String> q = new LinkedList<>();
        HashSet<String> set = new HashSet<>();
        q.add(beginWord);
        set.add(beginWord);

        int step = 1;

        while(!q.isEmpty()) {
            int size = q.size();
            step++;
            for (int i = 0; i < size; i++) {
                String curWord = q.poll();
                ArrayList<String> adjacentWord = getNextWord(curWord, wordList);
                for(String nextWord:adjacentWord) {
                    if(set.contains(nextWord)) {
                        continue;
                    }
                    if(nextWord.equals(endWord)) {
                        return step;
                    } 
                    if(!set.contains(nextWord)) {
                        q.offer(nextWord);
                        set.add(nextWord);
                    }
                }
            }

        }
        return 0;
    }

    public ArrayList<String> getNextWord(String word, Set<String> wordList) {
        ArrayList<String> result = new ArrayList<>();
        for(int i = 0; i < word.length(); i++) {
            for(char c = 'a'; c <= 'z'; c++) {
                String next = word.substring(0, i) + c + word.substring(i + 1);
                if(wordList.contains(next)) {
                    result.add(next);
                }
            }
        }

        return result;
    }
}

但是这个做法有一个问题,就是在大数据集的时候,由于每个单词变化的可能性过多,导致实际复杂度很高,解决方法就是 bi-directional,从两头开始往中间搜索,每次都去选择小的数据集的那头开始。

public class Solution {
    public int ladderLength(String beginWord, String endWord, Set<String> wordList) {
        if(wordList == null || wordList.isEmpty() || beginWord == null || endWord == null) {
            return 0;
        }
        if(beginWord.equals(endWord)) return 2;

        HashSet<String> beginSet = new HashSet<>();
        HashSet<String> endSet = new HashSet<>();

        // avoid circle
        wordList.remove(beginWord);
        wordList.remove(endWord);

        beginSet.add(beginWord);
        endSet.add(endWord);

        int step = 2;

        while(!beginSet.isEmpty()) {
            HashSet<String> nextLevel = new HashSet<>();
            for(String word : beginSet) {
                char[] chars = word.toCharArray();
                for(int i = 0; i < chars.length; i++) {
                    for(char c = 'a'; c <= 'z'; c++) {
                        chars[i] = c;
                        String newWord = String.valueOf(chars);

                        if(endSet.contains(newWord)) return step;
                        if(wordList.contains(newWord)) {
                            nextLevel.add(newWord);
                            wordList.remove(newWord);
                        }
                    }
                    // change back
                    chars = word.toCharArray();
                }

            }
            step++;

            // which side has less size
            if(nextLevel.size() < endSet.size()) {
                beginSet = nextLevel;
            } else {
                beginSet = endSet;
                endSet = nextLevel;
            }
        }

        return 0;
    }
}

Word Ladder II

返回所有最短距离的path

维护一个 Directed Graph 关系并且从某一个终点进行 dfs 返回所有 valid path.

这题应对大数据集的解法是 Bi-directional BFS 与 DFS 的结合,因为 bfs 过程中起点终点会调换,为了保证 path 的正确性要 keep track of direction.

有向图找最短距离用 BFS

有向图返回所有路径用 DFS

代码太麻烦了,就先放在这儿,有时间再慢慢写。

results matching ""

    No results matching ""