【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;
 }
}
相关推荐
Elias不吃糖3 小时前
LeetCode每日一练(209, 167)
数据结构·c++·算法·leetcode
铁手飞鹰4 小时前
单链表(C语言,手撕)
数据结构·c++·算法·c·单链表
悦悦子a啊4 小时前
项目案例作业(选做):使用文件改造已有信息系统
java·开发语言·算法
小殊小殊4 小时前
【论文笔记】知识蒸馏的全面综述
人工智能·算法·机器学习
无限进步_4 小时前
C语言动态内存管理:掌握malloc、calloc、realloc和free的实战应用
c语言·开发语言·c++·git·算法·github·visual studio
im_AMBER4 小时前
AI井字棋项目开发笔记
前端·笔记·学习·算法
Wadli4 小时前
项目2 |内存池1|基于哈希桶的多种定长内存池
算法
橘颂TA5 小时前
【剑斩OFFER】算法的暴力美学——判定字符是否唯一
算法·c/c++·结构与算法
雨中飘荡的记忆5 小时前
Redis 实战指南
java·redis