每日OJ题_BFS解决拓扑排序③_力扣LCR 114. 火星词典

目录

力扣LCR 114. 火星词典

解析代码


力扣LCR 114. 火星词典

LCR 114. 火星词典

难度 困难

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

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

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

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

  • 在第一个不同字母处,如果 s 中的字母在这门外星语言的字母顺序中位于 t 中字母之前,那么 s 的字典顺序小于 t 。
  • 如果前面 min(s.length, t.length) 字母都相同,那么 s.length < t.length 时,s 的字典顺序也小于 t 。

示例 1:

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

示例 2:

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

示例 3:

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

提示:

  • 1 <= words.length <= 100
  • 1 <= words[i].length <= 100
  • words[i] 仅由小写英文字母组成
class Solution {
public:
    string alienOrder(vector<string>& words) {

    }
};

解析代码

将题意理解清楚之后,这道题就变成了判断有向图是否有环,可以用拓扑排序解决。

如何如搜集信息(何建图):

  1. 两层 for 循环枚举出所有的两个字符串的组合。
  2. 然后利用指针,根据字典序规则找出信息。
class Solution {
    unordered_map<char, unordered_set<char>> edges; // 邻接表
    unordered_map<char, int> in; // 统计入度信息
    bool flag; // 处理边界情况, 类似str1 = a, b, c && str2 = a, b
    
public:
    string alienOrder(vector<string>& words) {
        for(auto& str : words) // 初始化入度哈希表
        {
            for(auto& ch : str)
            {
                in[ch] = 0;
            }
        }
        int sz = words.size();
        for(int i = 0; i < sz; ++i) // 建图
        {
            for(int j = i + 1; j < sz; ++j)
            {
                Add(words[i], words[j]);
                if(flag) // 不合法
                    return "";
            }
        }

        queue<char> q; // 拓扑排序
        for(auto& [a, b] : in) // 入度为0的点入队列
        {
            if(b == 0)
                q.push(a);
        }
        string ret;
        while(!q.empty())
        {
            char tmp = q.front();
            q.pop();
            ret += tmp;
            for(auto& ch : edges[tmp]) // 度为0的点指向的点的度减1
            {
                if(--in[ch] == 0)
                    q.push(ch);
            }
        }

        for(auto& [a, b] : in) // 返回
        {
            if(b != 0)
                return "";
        }
        return ret;
    }

    void Add(string& str1, string& str2) // 收集信息
    {
        int sz = min(str1.size(), str2.size()), i = 0;
        for(; i < sz; ++i)
        {
            if(str1[i] != str2[i])
            {
                char a = str1[i], b = str2[i]; // 前大后小
                if(!edges.count(a) || !edges[a].count(b)) // 防止存入重复信息   
                {
                    edges[a].insert(b);  // a -> b
                    in[b]++;
                }
                break;
            }
        }
        if(i == str2.size() && i < str1.size())
            flag = true; // 类似str1 = a, b, c && str2 = a, b
    }
};

上一篇:STM32学习和实践笔记(20):定时器-1.定时器介绍   STM32F1的定时器一共有8个,由2个基本定时器(TIMTIM7)、4个通用定时器(TIM2-TIM5)和2个高级定时器(TIMTIM8)组成。 基本定时器的功能最为简单,类似于51单片机内定时器。 通用定时器是在基本定时器的基础上扩展而来,增加了输入捕获与输出比较等功能。重点讲这种。 高级定时器又是在通用定时器基础上扩展而来,增加了可编程死区互补输出、重复计数器、带刹车(断路)功能,这些功能主要针对工业电机控制方面,一般情况下很少使用。 1.1 通用定时器简介   STM32F1的通用定时器包含一个 16 位自动重载计数器(CNT),该计数器由可编程预分频器(PSC)驱动。 STM32F1的通用定时器可用于多种用途,包括测量输入信号的脉冲宽度(输入捕获)或者生成输出波形(输出比较和PWM)等。 使用定时器预分频器和 RCC 时钟控制器预分频器,脉冲长度和波形周期可以在几个微秒到几个毫秒间调整。 STM32F1 的


下一篇:python实现假设检验-t检验