持续创造,加快生长!这是我参与「日新方案 6 月更文应战」的第7天,点击检查活动概况

标题描述

这是 LeetCode 上的 剑指 Offer II 114. 外星文字典数组排序 ,难度为 困难

Tag : 「图论」、「拓扑数组词数组初始化序」、「建图电脑黑屏却开着机」、「图论 BFS」

现有一种运用英语字母的外星文言语,这门言语的字母次序与英语次序不同。

给定一个字符串列表 words ,作为这数组排序门言语的词典,words 中的字符串现电脑截图已 按这门新言apple语的字母次序进数组排序行了排序电脑安全模式

请你根据该词典还原出此言语中已知的字母次序,并 按字母递加次序 摆放。数组和链表的差异若不存在合法字母次序,返回 "" 。若存在多种或许的合法字母次序电脑怎样重装系统,返回其间 任意一种 次序即可数组的定义

字符串 s 字典次序approve小于 字符串 t 有两种情况:

在第一个不同字母处,如果 s 中的字母在这门外星言语的数组算法字母次序中坐落 t 中字母之前,那么s 的字典次序小于 tgit教程
如果前面 min(s.length,数组的定义 t.length) 字母都相同,那么 s.lengt数组和链表的差异h数组词 < t.lengithub中文官网网页g算法的空间复杂度是指th 时,s 的字电脑开不了机典次序也小于 t

示例 1:

输入:words = ["wrt","wrf","er","ett","rftt"]
输出:"wertf"

示例 2:

输入:words = ["z","x"]
输出:"zx"

示例 3:

输入:words = ["z","x","z"]
输出:""
解说:不存在合法字母次序,因此返回 "" 。

提示:

  • 1<=words.length<=1001 <数组排序= words.电脑怎样重装系统length <= 100
  • 1&l电脑安全模式t;=words[i].length<=1001 <= words[i].length <= 100
  • wordsappearance[i] 仅由小写英文字母组成

建图 + 拓扑排序算法分析的目的是

为了便利,咱们称 wordsws,一起将两个字符串 ab 之间的字典序联系简称为「联系」。

APP于数组长度git教程和每个 ws[i]ws[i] 的最大长度均为 100100,咱们能够实现复杂度为 O(n3)算法剖析的目的是O(n^3) 复杂度的算算法的有穷性是指法。电脑怎样重装系统

首要简单想到,咱们早年往后处理算法工程师每个 ws[i]wsapplication[i],利用算法的空间复杂度是指 ws 数组本身已按字典序排序,然后经过 ws[i]ws[i]ws[j]ws[j] 的关数组排序系(其githubjj 的范围为 [0,i−1][0, i – 1]),来构电脑锁屏快捷键建字符之间的联系。

详细的,当咱们明确字符 c1c1c2c2 字典数组的定义序要小,能够建立从 c1c1c2c2 的有向边,一起计算添加 c1c1 的出度,添加 c2c2 的入度。

当建图完成后,咱们从一切算法的有穷性是指入度为 00 的点开始(意义为没有比这些字符字典序更小的字符),跑一遍拓扑排appearance序:在 BFS 过程中,不断的删点(出队的点能够看做从图中移除)和更新删去点的出边点的入度,若有新的入度为 00 的点,则将其进行算法的特征入队操作。

不了解拓扑排序的同学能够看前置 : 图论拓扑排序入门

若终究出队节点数量与总数量 cntcnt算法平,说明这是一张拓扑图(无环,字符之间不存在电脑截图字典序抵触)giticomfort是什么轮胎,出队的次序即是字典序,不然存在抵触,返回空串。

代码:

class Solution {
    int N = 26, M = N * N, idx = 0, cnt = 0;
    int[] he = new int[N], e = new int[M], ne = new int[M];
    int[] in = new int[N], out = new int[N];
    boolean[] vis = new boolean[26];
    void add(int a, int b) {
        e[idx] = b;
        ne[idx] = he[a];
        he[a] = idx++;
        out[a]++; in[b]++;
    }
    public String alienOrder(String[] ws) {
        int n = ws.length;
        Arrays.fill(he, -1);
        for (int i = 0; i < n; i++) {
            for (char c : ws[i].toCharArray()) {
                if (!vis[c - 'a'] && ++cnt >= 0) vis[c - 'a'] = true;
            }
            for (int j = 0; j < i; j++) {
                if (!build(ws[j], ws[i])) return "";
            }
        }
        Deque<Integer> d = new ArrayDeque<>();
        for (int i = 0; i < 26; i++) {
            if (vis[i] && in[i] == 0) d.addLast(i);
        }
        StringBuilder sb = new StringBuilder();
        while (!d.isEmpty()) {
            int u = d.pollFirst();
            sb.append((char)(u + 'a'));
            for (int i = he[u]; i != -1; i = ne[i]) {
                int j = e[i];
                if (--in[j] == 0) d.addLast(j);
            }
        }
        return sb.length() == cnt ? sb.toString() : "";
    }
    boolean build(String a, String b) {
        int n = a.length(), m = b.length(), len = Math.min(n, m);
        for (int i = 0; i < len; i++) {
            int c1 = a.charAt(i) - 'a', c2 = b.charAt(i) - 'a';
            if (c1 != c2) {
                add(c1, c2);
                return true;
            }
        }
        return n <= m;
    }
}
  • 时刻复杂度:令电脑开不了机 nn 为数组 ws 的长度,计算字符数的复杂度为 O(∑in电脑锁屏快捷键算法设计与剖析−1len(ws[i]))O(sum_{算法是指什么i}^{n – 1} lenapplication(w电脑蓝屏s[i])),建图复杂度为 O(n3)O(n^3);跑拓扑序构建答案复杂度 O(n2)O(n^2)。整体复杂度为 O(n3)O(n^3)approach
  • 空间复杂度:O(n2)O(n^2)

最后

这是咱们「刷穿 LeetCode」电脑快捷键系列文章的第 剑指 Offer II 114 篇,系列开始于 2021/01/电脑快捷键01,截止于起始日 Le数组和链表的区别etCode 上共有 1916 道标题,部分是有锁题,咱们将先把appear一切不带锁的标题刷完。

在这个系列文章里面,除了讲解解题思路以外,还会尽或许给出最为简洁的代码。如果涉及通解还会算法设计与分析相应的算法的有穷性是指代码模板。

为了便利各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:github.com/数组和链表的差异SharingSour… 。

在仓库地址里,你能够看到系列文章的算法的时刻复杂度取决于题解链接、系列文数组和链表的差异appetite的相应代码、LeetCode 原题链接和其他优选application题解。