• 269. Alien Dictionary



    June-27-2019

    比较难= = 用indegree的思路来做的,或者说拓扑的思路topological sort

    prevStr和tempStr,说明prevStr里的char在tempStr里的char之前.
    eg: abc&abd => d -> c 说明D前面有一个C

    要给所有出现的char建SET,记录前面有哪些char。 SET的大小代表char的indegree是几(前面有几个CHAR)
    上面的例子就这样 =>
    d : {c}

    遍历所有STR来比较,然后从indegree=0的开始删,和course schedule一个做法

    有问题的话会出现a的 set里有B, B的SET里有A,相互矛盾。

    有个隐藏条件
    "abc"
    "ab"
    是错的,空的永远排在任何字母之前,不容易想到,不用过分纠结这个。

    Time Complexity主要耗在遍历上 O(mn)

        public String alienOrder(String[] words) {
            
            Map<Character, Set<Character>> parentMap = new HashMap<>();
            
            for (String s : words) {
                for (char c : s.toCharArray()) {
                    if (!parentMap.containsKey(c)) {
                        parentMap.put(c, new HashSet<>());
                    }
                }
            }
            
            for (int i = 1; i < words.length; i ++) {
                String prevStr = words[i - 1];
                String tempStr = words[i];
                
                int len = Math.min(prevStr.length(), tempStr.length());
                for (int j = 0; j < len; j ++) {
                    char prevChar = prevStr.charAt(j);
                    char tempChar = tempStr.charAt(j);
                    
                    if (prevChar != tempChar) {                                     
                        if (!parentMap.get(tempChar).contains(prevChar)) {
                            parentMap.get(tempChar).add(prevChar);
                        }
                        break;
                    }
                    if (j == prevStr.length() - 1 && len + 1 == prevStr.length()) return "";
                }
                
            }
            
            ArrayDeque<Character> q = new ArrayDeque<>();
            for (Map.Entry<Character, Set<Character>> entry : parentMap.entrySet()) {
                if (entry.getValue().isEmpty()) {
                    q.offerLast(entry.getKey());
                }
            }
            
            StringBuilder sb = new StringBuilder();
            
            while (!q.isEmpty()) {
                char tempChar = q.pollFirst();
                parentMap.remove(tempChar);
                sb.append(tempChar);
                for (Map.Entry<Character, Set<Character>> entry : parentMap.entrySet()) {
                    if (entry.getValue().contains(tempChar)) {
                        entry.getValue().remove(tempChar);
                        if (entry.getValue().isEmpty()) {
                            q.offerLast(entry.getKey());
                        }
                    }
                }
            }
            
            if (parentMap.isEmpty()) {
                return sb.toString();
            } else {
                return "";
            }
            
        }
    

    =====================
    一刷。

    直接看的解法,大多数是用拓扑排序做的。

    说实话挺难的,直接看别人的CODE才理解。

    一开始也理解错了,单词里面的letter是没有顺序的,只是dictionary是按特殊顺序排列的。但是又不能只比较首字母,因为有可能首字母相同。

    Time: 假如26个字母。 不是很好算。。

    建图最差是N*N,但是这种情况发生时,整个图都是V,没有E。 就不用后面的拓扑排序了。拓扑排序是有边,才可以。。
    O(26²) + O(26) + O(26) * O(E) 大概这么个意思
    第一个26平方是建图,然后O(26)是入queue, O(26) * O(E)是拓扑排序。。

    这个题还有别的坑。

    "abc"
    "abcd"
    这样是没事的

    "abcd"
    "abc"
    这样是错的,‘ ’在‘d'之前是错的。
    有个rule没说,' ' shall before any letters,但是大家基本都以为Alien rule can be any rules it defines..= =

    public class Solution {
        public String alienOrder(String[] words) {
            if (words.length == 0) return "";
            
            Set<Character> letterSet = new HashSet<>();
            int[] inDegree = new int[26];
            Map<Character, HashSet<Character>> order = new HashMap<>();
            
            for (String s : words) {
                for (char c : s.toCharArray()) {
                    letterSet.add(c);
                }
            }
    
            for (int i = 1; i < words.length; i++) {
                String prevStr = words[i-1];
                String tempStr = words[i];
                
                if (prevStr.equals(tempStr)) continue;
                
                int len = Math.min(prevStr.length(), tempStr.length());
                
                for (int j = 0; j < len; j++) {
                    char prevC = prevStr.charAt(j);
                    char tempC = tempStr.charAt(j);
                    if (prevC != tempC) {
                        if (!order.containsKey(prevC)) {
                            order.put(prevC, new HashSet<>());
                        }
                        
                        if (!order.get(prevC).contains(tempC)) {
                            order.get(prevC).add(tempC);
                            inDegree[tempC - 'a'] ++;
                        }
                        break;
                    }
                    if (j == len - 1 && prevStr.length() > tempStr.length()) return "";
                }
            }
           
            
            Queue<Character> q = new LinkedList<>();
            for (int i = 0; i < inDegree.length; i++) {
                if (inDegree[i] == 0 && letterSet.contains((char)('a' + i))) {
                    q.offer((char)('a' + i));
                }
            }
            
            StringBuilder sb = new StringBuilder();
            while (!q.isEmpty()) {
                char tempChar = q.poll();
                sb.append(tempChar);
                if (order.containsKey(tempChar)) {
                    for (char c : order.get(tempChar)) {
                        inDegree[c - 'a'] --;
                        if (inDegree[c - 'a'] == 0) {
                            q.offer(c);
                        }
                    }
                }
            }
            
            if (sb.length() != letterSet.size()) {
                return "";
            } else {
                return sb.toString();
            }
        }
    }
    
  • 相关阅读:
    时间序列算法(平稳时间序列模型,AR(p),MA(q),ARMA(p,q)模型和非平稳时间序列模型,ARIMA(p,d,q)模型)的模型以及需要的概念基础学习笔记梳理
    Python两步实现关联规则Apriori算法,参考机器学习实战,包括频繁项集的构建以及关联规则的挖掘
    基于逻辑回归的利用欠采样处理类别不平衡的信用卡欺诈检测
    利用sklearn对MNIST手写数据集开始一个简单的二分类判别器项目(在这个过程中学习关于模型性能的评价指标,如accuracy,precision,recall,混淆矩阵)
    利用Sklearn实现加州房产价格预测,学习运用机器学习的整个流程(包含很多细节注解)
    Javax虚拟机-常见的JVM工具
    Java虚拟机-虚拟机字节码执行引擎
    Java虚拟机-虚拟机类加载机制
    Java虚拟机-类文件结构
    Java虚拟机-内存分配策略
  • 原文地址:https://www.cnblogs.com/reboot329/p/6158858.html
Copyright © 2020-2023  润新知