当前位置: 首页 > news >正文

拓扑排序 + 广度优先搜索法实例应用(二)

上篇文章,我们介绍了使用深度优先搜索实现拓扑排序,根据每个节点搜索完成的顺序反向得到拓扑排序。使用广度优先搜索实现拓扑排序,则可以正向得到拓扑排序。

首先计算每个节点的入度,只有入度为 0 的节点可能是拓扑排序中最前面的节点。当一个节点加入拓扑排序之后,该节点的所有相邻节点的入度都减 1,表示相邻节点少了一条入边。当一个节点的入度变成 0 ,则该节点前面的节点都已经加入拓扑排序,该节点也可以加入拓扑排序。

具体做法是:使用队列存储可以加入拓扑排序的节点,初始时将所有入度为 0 的节点入队列。每次将一个节点出队列并加入拓扑排序中,然后将该节点的所有相邻节点的入度都减 1 ,如果一个相邻节点的入度变成 0 ,则将该相邻节点入队列。重复上述操作,直到队列为空时,广度优先搜索结束。

如果有向图中无环,则每个节点都将加入拓扑排序,因此拓扑排序的长度等于字典中的字母个数。如果有向图中有环,则环中的节点不会加入拓扑排序,因此拓扑排序的长度小于字典中的字母个数。广度优先搜索结束时,判断拓扑排序的长度是否等于字典中的字母个数,即可判断有向图中是否有环。

  • 如果拓扑排序的长度等于字典中的字母个数,则拓扑排序包含字典中的所有字母,返回拓扑排序;
  • 如果拓扑排序的长度小于字典中的字母个数,则有向图中有环,不存在拓扑排序。如果拓扑排序的长度小于字典中的字母个数,则有向图中有环,不存在拓扑排序。

代码

Python3

class Solution: def alienOrder(self, words: List[str]) -> str: g = defaultdict(list) inDeg = {c: 0 for c in words[0]} for s, t in pairwise(words): for c in t: inDeg.setdefault(c, 0) for u, v in zip(s, t): if u != v: g[u].append(v) inDeg[v] += 1 break else: if len(s) > len(t): return "" q = [u for u, d in inDeg.items() if d == 0] for u in q: for v in g[u]: inDeg[v] -= 1 if inDeg[v] == 0: q.append(v) return ''.join(q) if len(q) == len(inDeg) else ""

Java

class Solution { Map<Character, List<Character>> edges = new HashMap<Character, List<Character>>(); Map<Character, Integer> indegrees = new HashMap<Character, Integer>(); boolean valid = true; public String alienOrder(String[] words) { int length = words.length; for (String word : words) { int wordLength = word.length(); for (int j = 0; j < wordLength; j++) { char c = word.charAt(j); edges.putIfAbsent(c, new ArrayList<Character>()); } } for (int i = 1; i < length && valid; i++) { addEdge(words[i - 1], words[i]); } if (!valid) { return ""; } Queue<Character> queue = new ArrayDeque<Character>(); Set<Character> letterSet = edges.keySet(); for (char u : letterSet) { if (!indegrees.containsKey(u)) { queue.offer(u); } } StringBuffer order = new StringBuffer(); while (!queue.isEmpty()) { char u = queue.poll(); order.append(u); List<Character> adjacent = edges.get(u); for (char v : adjacent) { indegrees.put(v, indegrees.get(v) - 1); if (indegrees.get(v) == 0) { queue.offer(v); } } } return order.length() == edges.size() ? order.toString() : ""; } public void addEdge(String before, String after) { int length1 = before.length(), length2 = after.length(); int length = Math.min(length1, length2); int index = 0; while (index < length) { char c1 = before.charAt(index), c2 = after.charAt(index); if (c1 != c2) { edges.get(c1).add(c2); indegrees.put(c2, indegrees.getOrDefault(c2, 0) + 1); break; } index++; } if (index == length && length1 > length2) { valid = false; } } }

复杂度分析

  • 时间复杂度:O(n×L +∣Σ∣) ,其中 n 是数组 words 的长度,即字典中的单词数, L 是字典中的平均单词长度,Σ 是字典中的字母集合。遍历字典构造有向图需要 O(n×L) 的时间,由于有向图包含最多 n−1 条边和 ∣Σ∣ 个节点,因此广度优先搜索需要 O(n +∣Σ∣) 的时间,总时间复杂度是 O(n×L + n +∣Σ∣) = O(n×L +∣Σ∣) 。
  • 空间复杂度:O(n+∣Σ∣) ,其中 n 是数组 words 的长度,即字典中的单词数,Σ 是字典中的字母集合。空间复杂度主要取决于存储有向图需要的空间,有向图包含最多 n−1 条边和 ∣Σ∣ 个节点。
http://www.jsqmd.com/news/1113694/

相关文章:

  • 智能画中画视频助手:Chrome扩展让多任务处理更高效
  • 如何快速掌握BepInEx:面向Unity游戏开发者的完整插件框架指南
  • Linux命令实战:从ps到grep,一篇搞定常用工具
  • 华为HCSP认证全攻略:考试流程、费用、通过率(2026版)
  • Three.js 加载3dtiles教程
  • 突破品类边界:智能模板机全域缝制解决方案
  • YOLOv10模型改进-Backbone改进-第53篇: YOLOv10改进策略【Backbone】| VGG16 Backbone替换
  • 从Notebook到生产环境的ML服务化实战:稳定性、可观测性与数据漂移监控
  • 模型服务化实战:从Notebook到生产就绪的12个关键环节
  • 深入解析OWASP A08:软件与数据完整性故障的防御实战
  • 计算机毕业设计之基于Java的NBA球队管理系统
  • AI Agent开发实战:核心技术、行业应用与优化策略
  • 开源与闭源大模型选型实战:从TCO、风险到混合架构决策
  • 《HarmonyOS技术精讲-Media Library Kit》之文件操作进阶
  • CentOS 7怎么搭建服务器监控告警?Prometheus与Alertmanager邮件通知教程
  • 条码/标签打印软件帮助车间标签打印混乱的难题终于理顺了
  • 2026中国AI先锋企业TOP30榜单正式揭晓|第一新声
  • AI Agent 工具接入多个模型时,API 中转层要先看哪些真实指标
  • PhotoGIMP终极指南:如何在3天内从Photoshop零成本迁移到开源图像编辑
  • 5分钟搞定WPS文献引用:免费开源插件让科研写作效率翻倍
  • VSCode——打开大型项目提示 `OOM (Out of Memory)` 的解决方案
  • mobaxterm vim +y复制到命令行卡住
  • Selenium自动化测试避坑指南:从环境配置到框架设计的实战解决方案
  • Windows微信QQ防撤回补丁RevokeMsgPatcher原理与配置详解
  • 数据库查询优化器<2>物理计划搜索和代价估计
  • Docker完整学习笔记
  • 直方图的替代方案:箱线图、KDE与小提琴图实战指南
  • Recrute Staffing Recruiting Agency WordPress Theme: Review, Installation Guide, and Setup Walkthro
  • std::move用法
  • Python 虚拟环境终极指南:16 款工具分类盘点,一文终结你的选择困难症