zoukankan      html  css  js  c++  java
  • 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来做,以后如果一种方法走不通的时候可以考虑下走另一种方法,而不是一直想着怎么优化写好的代码。。。

  • 相关阅读:
    汉明距离
    Go_go build 和 go install
    rabbitmq的简单介绍二
    rabbitmq的简单介绍一
    redis的订阅和发布
    python操作redis
    vmware虚拟机开机报附件中的错误的解决办法
    使用twised实现一个EchoServer
    python事件驱动的小例子
    mysql数据库的最基本的命令
  • 原文地址:https://www.cnblogs.com/alike/p/13290727.html
Copyright © 2011-2022 走看看