【BFS 解决拓扑排序】3. ⽕星词典(hard)

BFS 解决拓扑排序

拓扑排序简介

3. ⽕星词典(hard)

  1. 题⽬链接:LCR 114. ⽕星词典
  2. 题⽬描述:
    现有⼀种使⽤英语字⺟的外星⽂语⾔,这⻔语⾔的字⺟顺序与英语顺序不同。
    给定⼀个字符串列表 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] 仅由⼩写英⽂字⺟组成
  3. 解法:

    算法思路:
    将题意搞清楚之后,这道题就变成了判断有向图时候有环,可以⽤拓扑排序解决。
    如何搜集信息(如何建图):
    a. 两层 for 循环枚举出所有的两个字符串的组合;
    b. 然后利⽤指针,根据字典序规则找出信息。

算法代码:

java 复制代码
class Solution
{
 Map<Character, Set<Character>> edges = new HashMap<>(); // 邻接表
 Map<Character, Integer> in = new HashMap<>(); // 统计每个节点的⼊度
 boolean check;
 public String alienOrder(String[] words)
 {
	 // 1. 初始化⼊度哈希表 + 建图
	 for(String s : words)
	 {
		 for(int i = 0; i < s.length(); i++)
		 {
			 char ch = s.charAt(i);
			 in.put(ch, 0);
		 }
	 }
	 int n = words.length;
	 for(int i = 0; i < n; i++)
	 {
		 for(int j = i + 1; j < n; j++)
		 {
			 add(words[i], words[j]);
			 if(check == true) return "";
		 }
	 }
	 // 2. 拓扑排序
	 Queue<Character> q = new LinkedList<>();
	 for(char ch : in.keySet())
	 {
	 	if(in.get(ch) == 0) q.add(ch);
	 }
	 StringBuffer ret = new StringBuffer();
	 while(!q.isEmpty())
	 {
		 char t = q.poll();
		 ret.append(t);
		 if(!edges.containsKey(t)) continue;
		 for(char ch : edges.get(t))
		 {
			 in.put(ch, in.get(ch) - 1);
			 if(in.get(ch) == 0) q.add(ch);
		 }
	 }
	 // 3. 判断
	 for(char ch : in.keySet())
	 {
	 	if(in.get(ch) != 0) return "";
	 }
 	 return ret.toString();
 }
 public void add(String s1, String s2)
 {
	 int n = Math.min(s1.length(), s2.length());
	 int i = 0;
	 for( ; i < n; i++)
	 {
		 char c1 = s1.charAt(i), c2 = s2.charAt(i);
		 if(c1 != c2)
		 {
			 // c1 -> c2
			 if(!edges.containsKey(c1))
			 {
			 	edges.put(c1, new HashSet<>());
			 }
			 if(!edges.get(c1).contains(c2))
			 {
				 edges.get(c1).add(c2);
				 in.put(c2, in.get(c2) + 1);
			 }
			 break;
		 }
	 }
	 if(i == s2.length() && i < s1.length()) check = true;
 }
}
相关推荐
what丶k1 天前
深入解析Redis数据持久化:RBD机制原理、实操与生产最佳实践
数据库·redis·缓存
疯狂的喵1 天前
C++编译期多态实现
开发语言·c++·算法
scx201310041 天前
20260129LCA总结
算法·深度优先·图论
2301_765703141 天前
C++中的协程编程
开发语言·c++·算法
m0_748708051 天前
实时数据压缩库
开发语言·c++·算法
小魏每天都学习1 天前
【算法——c/c++]
c语言·c++·算法
智码未来学堂1 天前
探秘 C 语言算法之枚举:解锁解题新思路
c语言·数据结构·算法
Halo_tjn1 天前
基于封装的专项 知识点
java·前端·python·算法
春日见1 天前
如何避免代码冲突,拉取分支
linux·人工智能·算法·机器学习·自动驾驶
副露のmagic1 天前
更弱智的算法学习 day59
算法