leetcode127之单词接龙(无向图的构建)

无向图的构建与遍历

单词接龙题目链接

思路一:第一眼看到这个题,想到的解法是递归回溯,和最小基因变化很类似,因此编写代码如下:

 import java.util.List;
    class Solution {
        //典型的回溯问题,每次遍历字典找出未对比过的,然后标记,进入下一层,然后再回来取消标记
        int min=Integer.MAX_VALUE;
        public int ladderLength(String beginWord, String endWord, List<String> wordList) {
            boolean[] used=new boolean[wordList.size()];
            dfs(beginWord,endWord,wordList,0,used);
            return min==Integer.MAX_VALUE?0:min+1;
        }

        private void dfs(String beginWord, String endWord, List<String> wordList, int level, boolean[] used) {
            //terminator
            if(beginWord.equals(endWord)){
                min=Math.min(min,level);
                return;
            }
            for(int i=0;i<wordList.size();i++){
                if(used[i]==false){
                    int count=0;
                    for (int j=0;j<beginWord.length();j++){
                        if(beginWord.charAt(j)!=wordList.get(i).charAt(j))
                            count++;
                        if(count>1)
                            break;
                    }
                    if(count==1){
                        used[i]=true;
                        dfs(wordList.get(i),endWord,wordList,level+1,used);
                        used[i]=false;
                    }
                }
            }
        }
    }

然而结果是超出时间限制,只有22 / 43 个通过测试用例。于是看题解,得到以下思路:构建无向连接图,然后广度遍历

class Solution {
        //构建无向连接图,然后广度遍历
        public int ladderLength(String beginWord, String endWord, List<String> wordList) {
            HashSet<String> hashSet = new HashSet(wordList);
            HashMap<String, List<String>> hashMap = new HashMap<>();
            hashSet.add(beginWord);
            for (String s : hashSet) {
                List<String> list = new LinkedList<>();
                for (int i = 0; i < s.length(); i++) {
                    char x = s.charAt(i);
                    for (char c = 'a'; c <= 'z'; c++) {
                        if (c == x)
                            continue;
                        String tmp = (i > 0 ? s.substring(0, i) : "") + c + (i + 1 < s.length() ? s.substring(i + 1, s.length()) : "");
                        if (hashSet.contains(tmp))
                            list.add(tmp);
                    }
                }
                hashMap.put(s, list);
            }
            Set<String> used = new HashSet<>();
            Queue<String> queue = new ArrayDeque();
            queue.add(beginWord);
            int level = 0;
            while (!queue.isEmpty()) {
                int size = queue.size();
                for (int i = 0; i < size; i++) {
                    String s = queue.poll();
                    if (!used.contains(s)) {
                        used.add(s);
                        if (s.equals(endWord))
                            return level + 1;
                        for (String x : hashMap.get(s))
                            queue.add(x);
                    }
                }
                level++;
            }
            return used.contains(endWord)?level:0;
        }
    }

这里构建无向图采用的是HashMap,key值设为当前节点,Value通过链表定义其邻接点,然后进行遍历与记录。
提交正确解后发现时间只击败了46%的人,遂去看最快的代码,发现用到的是一个双向搜索策略(题解中也有),而且代码更精炼,这里也贴一下记录

class Solution {
    public int ladderLength(String beginWord, String endWord, List<String> wordList) {
        Set<String> beginSet = new HashSet<>();
        Set<String> endSet = new HashSet<>();
        beginSet.add(beginWord);
        endSet.add(endWord);
        Set<String> dict = new HashSet<>(wordList);
        if(!dict.contains(endWord)) return 0;
        return search(beginSet, endSet, dict, 1);
    }
    
    private int search(Set<String> beginSet, Set<String> endSet, Set<String> dict, int cnt){
        if(beginSet.isEmpty() || endSet.isEmpty()) return 0;
        cnt++;
        dict.removeAll(beginSet);
        Set<String> nextSet = new HashSet<>();
        for(String str : beginSet){
            char[] chs = str.toCharArray();
            for(int i = 0; i < chs.length; i++){
                char c = chs[i];
                for(char j = 'a'; j <= 'z'; j++){
                    chs[i] = j;
                    String tmp = new String(chs);
                    if(!dict.contains(tmp)) continue;
                    if(endSet.contains(tmp)) return cnt;
                    nextSet.add(tmp);
                }
                chs[i] = c;
            }
        }
        return nextSet.size() > endSet.size() ? search(endSet, nextSet, dict, cnt) : search(nextSet, endSet, dict, cnt);
    }
}

这题和最小基因变化很类似,但是在那里用到的0ms解法在这里失效了,因此也学会了一种新的解法,其实很多题都既可以用dfs也可以用bfs来做,以后如果一种方法走不通的时候可以考虑下走另一种方法,而不是一直想着怎么优化写好的代码。。。

posted @ 2020-07-12 23:37  浮尘2333  阅读(170)  评论(0编辑  收藏  举报