目录
力扣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, 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
}
};