• [LeetCode] 269. Alien Dictionary


    There is a new alien language which uses the latin alphabet. However, the order among letters are unknown to you. You receive a list of non-empty words from the dictionary, where words are sorted lexicographically by the rules of this new language. Derive the order of letters in this language.

    Example 1:

    Input:
    [
      "wrt",
      "wrf",
      "er",
      "ett",
      "rftt"
    ]
    
    Output: "wertf"
    

    Example 2:

    Input:
    [
      "z",
      "x"
    ]
    
    Output: "zx"
    

    Example 3:

    Input:
    [
      "z",
      "x",
      "z"
    ] 
    
    Output: "" 
    
    Explanation: The order is invalid, so return "".
    

    Note:

    • You may assume all letters are in lowercase.
    • If the order is invalid, return an empty string.
    • There may be multiple valid order of letters, return any one of them is fine.

    火星词典。

    现有一种使用字母的全新语言,这门语言的字母顺序与英语顺序不同。

    假设,您并不知道其中字母之间的先后顺序。但是,会收到词典中获得一个 不为空的 单词列表。因为是从词典中获得的,所以该单词列表内的单词已经 按这门新语言的字母顺序进行了排序。

    您需要根据这个输入的列表,还原出此语言中已知的字母顺序。

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/alien-dictionary
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

    思路是拓扑排序,我这里给出的是BFS的解法。首先给每个牵涉到的字母都分别给一个入度1,同时需要计算这里一共牵涉到多少个不同的字母count。之后再次遍历input,这一次需要创建graph的边。创建的方式是用hashmap,分如下几个比较细节的步骤。

    单词两两比较,发现第一个不同的字母之后,比如这个例子,

    "wrt"和"wrf"

    就把t当做key放入hashmap,map的value是一个hashset,再把f加入这个hashset,同时也把f的入度++,之后立即break(因为每两个单词之间其实只能最多得到两个字母之间的相对顺序)。照此遍历完所有的单词之后,根据入度表创建graph,还是把入度为1的字母加入queue。创建了graph之后,再来就是跟course schedule一样用BFS遍历每一条边,弹出queue的那一刻就将遍历到的字符append到结果集中;同时看这个字符是否在hashmap中,若在,也要去查看他对应的hashset里面有没有入度为1的字母,若有也要加入queue。最后如果res结果集的长度跟count不一致则返回空字符串。

    时间O(V + E)

    空间O(n) - 单词个数

    Java实现

     1 class Solution {
     2     public static String alienOrder(String[] words) {
     3         // corner case
     4         if (words == null || words.length == 0) {
     5             return "";
     6         }
     7 
     8         // normal case
     9         StringBuilder res = new StringBuilder();
    10         // 记录字典序
    11         HashMap<Character, Set<Character>> map = new HashMap<>();
    12         int[] degree = new int[26];
    13         int count = 0;
    14         for (String word : words) {
    15             for (char c : word.toCharArray()) {
    16                 if (degree[c - 'a'] == 0) {
    17                     count++;
    18                     degree[c - 'a'] = 1;
    19                 }
    20             }
    21         }
    22 
    23         // 两两单词比较字母的不同
    24         for (int i = 0; i < words.length - 1; i++) {
    25             char[] cur = words[i].toCharArray();
    26             char[] next = words[i + 1].toCharArray();
    27             // corner case, 会有非法情况
    28             // 如果某个单词出现在他的前缀之前,则说明这个排序是不合法的
    29             // ["abc", "ab"]
    30             if (cur.length > next.length && words[i].startsWith(words[i + 1])) {
    31                 return "";
    32             }
    33 
    34             // normal case, created the graph
    35             int len = Math.min(cur.length, next.length);
    36             for (int j = 0; j < len; j++) {
    37                 if (cur[j] != next[j]) {
    38                     if (!map.containsKey(cur[j])) {
    39                         map.put(cur[j], new HashSet<>());
    40                     }
    41                     if (map.get(cur[j]).add(next[j])) {
    42                         degree[next[j] - 'a']++;
    43                     }
    44                     break;
    45                 }
    46             }
    47         }
    48 
    49         Queue<Character> queue = new LinkedList<>();
    50         for (int i = 0; i < 26; i++) {
    51             if (degree[i] == 1) {
    52                 queue.offer((char) ('a' + i));
    53             }
    54         }
    55 
    56         while (!queue.isEmpty()) {
    57             char c = queue.poll();
    58             res.append(c);
    59             if (map.containsKey(c)) {
    60                 for (char ch : map.get(c)) {
    61                     if (--degree[ch - 'a'] == 1) {
    62                         queue.offer(ch);
    63                     }
    64                 }
    65             }
    66         }
    67         if (res.length() != count) {
    68             return "";
    69         }
    70         return res.toString();
    71     }
    72 }

    相关题目

    207. Course Schedule

    210. Course Schedule II

    269. Alien Dictionary

    310. Minimum Height Trees

    953. Verifying an Alien Dictionary

    LeetCode 题目总结

  • 相关阅读:
    2018面试题
    输入对象和数量制造批量假数据
    前端监控和前端埋点方案设计--摘抄
    给页面上所有的a标签增加随机数每次点击保证最新
    给所有ajax请求增加随机数
    打印2018年的日历
    为图片添加文字 canvas
    地图搜索地图定位标注
    地图拖拽定位
    智能搜索地图
  • 原文地址:https://www.cnblogs.com/cnoodle/p/12657598.html
Copyright © 2020-2023  润新知