Leetcode 269. 火星词典

1.题目基本信息

1.1.题目描述

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

给定一个字符串列表 words ,作为这门语言的词典,words 中的字符串已经 按这门新语言的字母顺序进行了排序 。

请你根据该词典还原出此语言中已知的字母顺序,并 按字母递增顺序 排列。若不存在合法字母顺序,返回 "" 。若存在多种可能的合法字母顺序,返回其中 任意一种 顺序即可。

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

  • 在第一个不同字母处,如果 s 中的字母在这门外星语言的字母顺序中位于 t 中字母之前,那么 s 的字典顺序小于 t 。

  • 如果前面 min(s.length, t.length) 字母都相同,那么 s.length < t.length 时,s 的字典顺序也小于 t 。

1.2.题目地址

https://leetcode.cn/problems/alien-dictionary/description/

2.解题方法

2.1.解题思路

kahn算法 / DFS

2.2.解题步骤

kahn算法进行拓扑排序步骤

  • 第一步,根据"有序"的words数组构建各个字符之间的有向图,使用邻接表进行存储;并在建图的过程中统计各个结点的入度信息到inDegree哈希表中

    • 1.1.将所有字符都初始化到图中,并初始化它们入度为0

    • 1.2.遍历相邻单词组,构建图,并填充入度到inDegree哈希表

      • 1.2.1.将边添加到图中

      • 1.2.2.统计入度

      • 1.2.3.word1和word2的前缀相同且word1的长度大于word2的长度是不合法的情况,直接返回空字符串

  • 第二步,kahn算法进行拓扑排序。先判断图中是否有环,如果无环,返回任意一个拓扑排序的序列,如果有环,返回空字符串

    • 2.1.将入度为0的结点添加到队列中,并初始化拓扑排序序列数组

    • 2.2.kahn算法进行拓扑排序

  • 第三步,如果inDegree中所有结点的入度都为0,说明无环

DFS算法步骤

  • 第一步,构建出现的字母集合

  • 第二步,构建有向图的邻接表和入度字典

  • 第三步,DFS进行拓扑排序

3.解题代码

kahn算法版本代码

from collections import defaultdict, deque

class Solution:
    def alienOrder(self, words: List[str]) -> str:
        # 思路:拓扑排序
        # 第一步,根据"有序"的words数组构建各个字符之间的有向图,使用邻接表进行存储;并在建图的过程中统计各个结点的入度信息到inDegree哈希表中
        graph = defaultdict(list)
        inDegree = defaultdict(int)
        # 1.1.将所有字符都初始化到图中,并初始化它们入度为0
        charsSet = set()
        for w in words:
            for c in w:
                charsSet.add(c)
        for c in charsSet:
            graph[c] = []
            inDegree[c] = 0
        # 1.2.遍历相邻单词组,构建图,并填充入度到inDegree哈希表
        n = len(words)
        for i in range(1, n):
            word1, word2 = words[i - 1], words[i]
            j = 0
            length1, length2 = len(word1), len(word2)
            while j < min(length1, length2):
                if word1[j] != word2[j]:
                    # 1.2.1.将边添加到图中
                    graph[word1[j]].append(word2[j])
                    # 1.2.2.统计入度
                    inDegree[word2[j]] += 1
                    break
                j += 1
            # 1.2.3.word1和word2的前缀相同且word1的长度大于word2的长度是不合法的情况,直接返回空字符串
            if j == min(length1, length2) and length1 > length2:
                return ""
        # print(graph)
        # print(inDegree)
        # 第二步,kahn算法进行拓扑排序。先判断图中是否有环,如果无环,返回任意一个拓扑排序的序列,如果有环,返回空字符串
        # 2.1.将入度为0的结点添加到队列中,并初始化拓扑排序序列数组
        arr = []    # 拓扑排序的序列
        que = deque()
        for node in graph.keys():
            if inDegree[node] == 0:
                que.append(node)
                arr.append(node)
        # 2.2.kahn算法进行拓扑排序
        while que:
            for _ in range(len(que)):
                node = que.popleft()
                del inDegree[node]
                for neighNode in graph[node]:
                    inDegree[neighNode] -= 1
                    if inDegree[neighNode] == 0:
                        que.append(neighNode)
                        arr.append(neighNode)
        # print(inDegree, arr)
        # 第三步,如果inDegree中所有结点的入度都为0,说明无环
        result = "".join(arr) if len(inDegree) == 0 else ""
        return result

dfs算法版本代码

from collections import defaultdict, deque

class Solution:
    # 思路一:DFS
    def alienOrder(self, words: List[str]) -> str:
        length=len(words)
        # 构建出现的字母集合
        lettersSet=set()
        for word in words:
            for letter in word:
                lettersSet.add(letter)
        # 构建图、入度字典
        graph={letter:[] for letter in lettersSet}
        inDict=defaultdict(int)
        for i in range(1,length):
            preWord=words[i-1]
            word=words[i]
            isNormalEnd=True
            for preLetter,letter in zip(preWord,word):
                # print(preLetter,letter)
                if preLetter!=letter:
                    graph[preLetter].append(letter)
                    inDict[letter]+=1
                    isNormalEnd=False
                    break
            if isNormalEnd:
                # print("t4",preWord,word)
                if len(preWord)>len(word):
                    return ""
        # print("t1",graph,inDict,lettersSet)
        # dfs
        visiting=set()
        visited=set()
        stack=[]
        # 返回True代表无环
        def dfs(node):
            if node in visited:
                return True
            if node in visiting:
                return False
            visiting.add(node)
            for subNode in graph[node]:
                noCircle=dfs(subNode)
                if not noCircle:
                    return False
            visiting.remove(node)
            visited.add(node)
            stack.append(node)
            return True
        for node in list(graph.keys()):
            noCircle=dfs(node)
            if not noCircle:
                return ""
        return "".join(stack[::-1])

4.执行结果

posted @ 2025-06-01 09:41  Geek0070  阅读(19)  评论(0)    收藏  举报