news 2026/6/24 3:51:07

dfs代码问题根源分析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
dfs代码问题根源分析

目录

1. 核心超时原因

2. 正确建图思路

优化后完整代码(DFS 版,AC 不超时)

关键优化点对比

旧代码缺陷

新版优化点

补充:BFS 迭代版(防止递归深度过大栈溢出)

原理简单说明


1. 核心超时原因

  1. 双重循环 O (n²)dfs 里写了for(int i = 0; i < n; i++),每次遍历全部 n 个节点,n 大时直接爆炸。
  2. List.contains () 是 O (k) 线性查找graph.get(pos).contains(i)每次遍历邻接表,双重嵌套复杂度极高。
  3. 图只存单向边,没有标记原道路方向原数组connections=[a,b]代表原生道路 a→b,需要反转;而 b→a 是虚拟反向边不用反转。你现在单纯存单向列表,判断是否要翻转的逻辑低效且容易出错。

2. 正确建图思路

每条道路[u, v]

  • u → v:真实道路,走到这里需要翻转,标记权重1
  • v → u:虚拟反向通路,不用翻转,标记权重0邻接表存(邻接点, 是否需要翻转),一次遍历就能拿到所有邻居,不用循环全部节点。

优化后完整代码(DFS 版,AC 不超时)

import java.util.ArrayList; import java.util.List; class Solution { int res = 0; public int minReorder(int n, int[][] connections) { // 邻接表:List<int[]>,每个数组 {neighbor, cost} // cost=1:原道路是 当前节点→邻居,需要翻转 // cost=0:虚拟反向边,不需要翻转 List<List<int[]>> graph = new ArrayList<>(); for (int i = 0; i < n; i++) { graph.add(new ArrayList<>()); } // 构建双向带权图 for (int[] edge : connections) { int u = edge[0]; int v = edge[1]; graph.get(u).add(new int[]{v, 1}); // u->v 真实路,代价+1 graph.get(v).add(new int[]{u, 0}); // v->u 虚拟路,代价0 } boolean[] visited = new boolean[n]; dfs(graph, 0, visited); return res; } private void dfs(List<List<int[]>> graph, int cur, boolean[] visited) { visited[cur] = true; // 只遍历当前节点的所有邻接点,O(邻接点数量),不是O(n) for (int[] neighborInfo : graph.get(cur)) { int next = neighborInfo[0]; int cost = neighborInfo[1]; if (!visited[next]) { res += cost; dfs(graph, next, visited); } } } }

关键优化点对比

旧代码缺陷

  1. dfs 循环0~n-1所有节点,n=5e4 直接超时
  2. contains()线性查找,双重循环叠加复杂度爆炸
  3. 无法快速区分 “原正向路 / 虚拟反向路”,逻辑绕且慢

新版优化点

  1. 邻接表存储带权边一次遍历当前节点所有邻居,时间复杂度 O (n),总节点 + 边只遍历一次
  2. 去掉List.contains(),完全消除线性查找开销
  3. 建图时直接标记是否需要翻转,遍历邻居时直接累加代价,逻辑极简
  4. 整体时间复杂度 O (n),空间 O (n),大数据量无压力

补充:BFS 迭代版(防止递归深度过大栈溢出)

当 n 极大时,递归 DFS 会栈溢出,可用 BFS:

import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Queue; class Solution { public int minReorder(int n, int[][] connections) { List<List<int[]>> graph = new ArrayList<>(); for (int i = 0; i < n; i++) graph.add(new ArrayList<>()); for (int[] e : connections) { int u = e[0], v = e[1]; graph.get(u).add(new int[]{v, 1}); graph.get(v).add(new int[]{u, 0}); } boolean[] vis = new boolean[n]; Queue<Integer> q = new LinkedList<>(); q.offer(0); vis[0] = true; int ans = 0; while (!q.isEmpty()) { int cur = q.poll(); for (int[] info : graph.get(cur)) { int next = info[0], cost = info[1]; if (!vis[next]) { vis[next] = true; ans += cost; q.offer(next); } } } return ans; } }

原理简单说明

题目要求所有城市能通向 0,从 0 向外遍历:

  • 如果遍历方向和原始道路方向一致(u→v),说明这条路远离 0,必须翻转,计数 + 1
  • 如果是反向虚拟边(v→u),道路本身朝向 0,无需翻转,不计入结果 遍历所有节点累加翻转次数即为答案。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/24 3:48:44

TikTok国际版下载避坑指南:2026年最新完整教程

最近很多朋友问我&#xff0c;怎么在国内下载TikTok国际版。说实话&#xff0c;这个问题比想象中复杂一点&#xff0c;但只要搞清楚几个关键点&#xff0c;整个流程其实没那么玄乎。今天就把我们团队实操验证过的方法分享出来&#xff0c;给想做TikTok运营或者想了解海外版抖音…

作者头像 李华
网站建设 2026/6/24 3:45:40

独立产品从0到1:技术人的产品打磨方法论

独立产品从0到1&#xff1a;技术人的产品打磨方法论 一、独立开发的最大陷阱&#xff1a;用技术思维做产品决策 技术人做独立产品&#xff0c;最容易掉进"技术驱动"的坑。花三个月打磨架构、优化性能、完善 CI/CD&#xff0c;上线后发现没人用。问题不是技术不够好&…

作者头像 李华
网站建设 2026/6/24 3:43:42

【共创季稿事节】动图魔方技术拆解 03:HarmonyOS 6.1 本地优先 GIF 工具:素材选择、文件 URI、相册保存与系统分享

SEO 信息SEO 标题&#xff1a;【共创季稿事节】动图魔方技术拆解 03&#xff1a;HarmonyOS 6.1 本地优先 GIF 工具素材链路实战SEO 摘要&#xff1a;基于 HarmonyOS NEXT / ArkTS 项目“动图魔方”&#xff0c;拆解一个不依赖登录态、不申请网络权限的 GIF 工具如何完成本地优先…

作者头像 李华
网站建设 2026/6/24 3:33:50

狼享Lite版(LAN Share Lite) 教程

狼享Lite版(LAN Share Lite) 教程 永久免费、跨平台的 LAN Share Lite。 一句话定位 狼享Lite版(LAN Share Lite) 是一个无需上传第三方云端、将局域网带宽最大化、打开浏览器即可使用的局域网文件共享工具&#xff0c;适合个人、家庭、工作室和临时协作。 系列目录 第一组&…

作者头像 李华
网站建设 2026/6/24 3:33:46

性价比高的中高端整装家居公司

在家装行业中&#xff0c;寻找一家性价比高的中高端整装家居公司是众多消费者的目标。青海百佳居装饰就是这样一家值得推荐的企业&#xff0c;它能有效解决消费者在家装过程中遇到的各种痛点&#xff0c;为消费者提供高品质的一站式家装解决方案。解决前期选购痛点专业指导避免…

作者头像 李华
网站建设 2026/6/24 3:32:22

Prompt

一、Coze中提示词 1. Coze中提示词分类Coze中有两种提示词&#xff1a;系统提示词、用户提示词&#xff1b; 1.系统提示词&#xff1a;①定义&#xff1a;大模型角色定位回复逻辑&#xff1b;②位置&#xff1a;在Agent的“人设与回复逻辑"中设置&#xff1b;③作用&#…

作者头像 李华