目录
力扣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) {}
};
解析代码
将题意理解清楚之后,这道题就变成了判断有向图是否有环,可以用拓扑排序解决。
如何如搜集信息(何建图):
- 两层 for 循环枚举出所有的两个字符串的组合。
- 然后利用指针,根据字典序规则找出信息。
class Solution {unordered_map<char, unordered_set<char>> edges; // 邻接表unordered_map<char, int> in; // 统计入度信息bool flag; // 处理边界情况, 类似str1 = a, b, c && str2 = a, bpublic: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 -> bin[b]++;}break;}}if(i == str2.size() && i < str1.size())flag = true; // 类似str1 = a, b, c && str2 = a, b}
};