深度优先搜索(DFS)算法详解:C++实现、优化与应用场景
1. 项目概述为什么DFS是算法工程师的“瑞士军刀”深度优先搜索简称DFS几乎是我在面试新人或者带实习生时第一个会考察的算法思想。它不像动态规划那样需要复杂的状态定义也不像贪心算法那样考验直觉DFS更像是一种朴实无华但威力巨大的“元工具”。无论是解决迷宫问题、排列组合、图论中的连通性判断还是在游戏AI中模拟决策树DFS都扮演着核心角色。对于C开发者而言熟练掌握DFS不仅仅是刷题的需要更是构建复杂系统逻辑、处理树形或图形数据结构的底层思维模型。很多看似高级的问题比如文件系统的遍历、依赖解析、甚至是某些编译优化其内核都闪烁着DFS的思想光芒。今天我们就抛开那些教科书式的定义从一线开发者的视角彻底拆解DFS在C中的实现、优化和应用中的那些“坑”与“技巧”。2. 核心思想与递归实现像探险家一样思考2.1 DFS的本质一条路走到黑不行就回头你可以把DFS想象成一个在迷宫里执着的探险家。他的策略很简单从起点出发随机或按既定规则选择一个方向前进并在这个新位置重复同样的过程——继续选择下一个方向深入。如果走到死胡同没有未探索的相邻通道他就退回到上一个岔路口尝试之前没选过的另一条路。这个过程会一直持续直到找到出口或者探索完所有可能的路径。在计算机科学中这个“迷宫”就是我们的数据结构——通常是树Tree或图Graph。 “岔路口”是节点Node “通道”是边Edge。 DFS的核心在于对每一个可能的分支路径深入到不能再深入为止并且每个节点只访问一次。递归实现是DFS最直观的表达因为它完美契合了“重复相同过程”的思想。我们来看一个经典的二叉树前序遍历这就是DFSstruct TreeNode { int val; TreeNode *left; TreeNode *right; TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} }; void dfs_preorder(TreeNode* node) { // 递归终止条件到达空节点死胡同 if (node nullptr) { return; } // 处理当前节点相当于在迷宫当前位置做个标记 std::cout node-val ; // 深入探索左子树选择一条路走下去 dfs_preorder(node-left); // 当左子树探索完毕退回到岔路口再探索右子树尝试另一条路 dfs_preorder(node-right); }这段代码清晰地展示了DFS递归的三要素递归函数定义dfs_preorder负责处理以当前节点为根的子树。递归终止条件当节点为空时返回这是避免无限递归的关键。递归递推关系调用自身先处理本节点然后对其左孩子和右孩子分别调用自己。注意递归虽然简洁但它隐式地使用了系统的调用栈Call Stack来保存“回溯点”即返回地址和局部变量。栈的深度等于递归深度对于深度很大的树或图例如链状树有栈溢出Stack Overflow的风险。2.2 递归实现的通用模板与关键细节对于更一般的图或复杂场景我们需要记录节点是否被访问过避免重复访问陷入循环。下面是一个针对图邻接表表示的DFS递归通用模板#include vector #include unordered_set using namespace std; void dfs_recursive(int node, const vectorvectorint graph, unordered_setint visited) { // 1. 标记当前节点为已访问 visited.insert(node); // 2. 处理当前节点根据实际问题进行如打印、收集等 process(node); // 3. 遍历当前节点的所有邻居 for (int neighbor : graph[node]) { // 如果邻居未被访问则深入探索 if (visited.find(neighbor) visited.end()) { dfs_recursive(neighbor, graph, visited); } // 如果已访问则跳过避免循环 } // 4. 函数返回即意味着回溯到上一层调用者 }这里有几个极易出错的细节访问标记的时机必须在递归调用之前进行标记。如果放在调用之后或者在处理邻居的循环内标记可能会导致节点被多次压入递归栈造成逻辑错误甚至栈溢出。递归深度的考量在C中默认的栈空间有限通常几MB。在解决如“网格类DFS”岛屿问题时如果网格很大如1000x1000递归深度可能达到百万级必然导致栈溢出。这是递归DFS最大的局限性。路径恢复回溯在需要记录完整路径的问题中如全排列、组合总和需要在递归调用前将当前选择加入路径在递归调用后将其从路径中移除。这是回溯算法的核心操作体现了DFS“试错”与“撤销”的思想。// 以全排列问题为例展示回溯 vectorvectorint result; vectorint path; void backtrack(vectorint nums, vectorbool used) { if (path.size() nums.size()) { result.push_back(path); // 找到一组排列 return; } for (int i 0; i nums.size(); i) { if (used[i]) continue; // 数字已使用跳过 used[i] true; // 做出选择 path.push_back(nums[i]); backtrack(nums, used); // 递归探索下一层 path.pop_back(); // 撤销选择回溯 used[i] false; // 撤销选择回溯 } }3. 迭代实现与显式栈将递归“摊开”给你看由于递归的栈溢出风险在实际工程和竞赛中我们经常需要将DFS改写为迭代版本手动管理一个栈Stack来模拟递归过程。这不仅能规避栈深度限制有时也让程序逻辑更清晰便于调试。3.1 迭代DFS的基本框架迭代DFS的核心是使用一个栈std::stack来显式保存待访问节点或需要回溯的路径信息。基本步骤如下将起始节点压入栈。当栈不为空时循环 a. 弹出栈顶元素作为当前访问节点。 b. 如果该节点未被访问则处理它并标记为已访问。 c.将其所有未访问的邻居节点压入栈中。这里有一个关键点为了模拟递归的深度优先后进先出我们需要将邻居逆序压栈以保证第一个被压入的邻居最后被弹出从而先探索最后一个被压入的邻居等等这听起来有点绕。实际上为了保证和某种递归顺序一致可能需要逆序。但最简单的迭代DFS顺序可能与前序、后序不同但它依然是深度优先的。我们来看一个二叉树迭代前序遍历的例子它非常直观void dfs_iterative_preorder(TreeNode* root) { if (root nullptr) return; stackTreeNode* stk; stk.push(root); while (!stk.empty()) { TreeNode* node stk.top(); stk.pop(); // 处理当前节点 cout node-val ; // 注意为了达到 根-左-右 的顺序需要先将右孩子入栈再将左孩子入栈 // 这样左孩子会先被弹出处理 if (node-right) stk.push(node-right); if (node-left) stk.push(node-left); } }3.2 处理图与复杂状态的迭代DFS对于图或者需要保存路径的状态迭代实现会稍微复杂一些因为我们需要在栈里存储更多信息。常见的方法是使用一个结构体或pair来封装节点和到达该节点的路径或其它状态。// 示例使用栈实现图的DFS并记录路径 void dfs_iterative_with_path(int start, int target, const vectorvectorint graph) { stackpairint, vectorint stk; // 栈元素当前节点 从起点到当前节点的路径 unordered_setint visited; stk.push({start, {start}}); visited.insert(start); while (!stk.empty()) { auto [current_node, current_path] stk.top(); stk.pop(); if (current_node target) { // 找到目标输出路径 for (int n : current_path) cout n ; cout endl; // 注意这里通常根据问题决定是return还是continue找所有路径 // return; // 只找一条路径 } // 遍历邻居注意这里为了和递归顺序有可比性可以逆序遍历 for (auto it graph[current_node].rbegin(); it ! graph[current_node].rend(); it) { int neighbor *it; if (visited.find(neighbor) visited.end()) { visited.insert(neighbor); vectorint new_path current_path; // 复制路径 new_path.push_back(neighbor); stk.push({neighbor, new_path}); } } } }迭代实现的优缺点分析优点避免栈溢出使用堆Heap内存的栈数据结构空间通常远大于系统调用栈。状态更清晰所有中间状态都显式地保存在自己的栈或辅助结构中调试时更容易观察。性能可能更优避免了递归的函数调用开销压参、跳转、返回等对于极深遍历迭代版本可能更快。缺点代码复杂度高尤其是需要维护路径或复杂状态时代码不如递归简洁优雅。容易出错手动管理栈和访问标记的顺序需要格外小心否则容易造成重复访问或漏访问。实操心得在平时开发中如果问题规模明确不会导致栈溢出我优先使用递归因为其思路清晰易于验证。而在面对未知输入规模如处理用户上传的图数据或深度可能很大的场景如棋盘搜索迭代实现是更稳健的选择。在LeetCode等平台刷题时了解两种写法都至关重要。4. DFS的典型应用场景与实战解析理解了DFS的两种实现方式我们来看看它在哪些具体问题上大放异彩。我会结合代码和解题思路让你感受DFS是如何“化繁为简”的。4.1 排列、组合、子集问题回溯法这是DFS回溯最经典的应用领域。问题的解空间通常可以构成一棵树DFS负责系统地遍历这棵树的所有可能分支。全排列Permutations给定一个不含重复数字的数组返回其所有可能的排列。解空间树深度为n数组长度每个节点代表一个部分排列。DFS通过used数组避免重复使用数字并通过回溯恢复状态。组合总和Combination Sum给定数组和目标和找出所有和为目标的组合数字可重复使用。解空间树深度由目标和决定。DFS需要决定在每一层是“选当前数”还是“跳过当前数”并注意去重如果数组有重复数字。子集Subsets求数组的所有子集。解空间树每个节点有两个分支包含当前元素或不包含。DFS遍历所有叶子节点即为所有子集。以子集问题为例看DFS如何优雅解决vectorvectorint subsets(vectorint nums) { vectorvectorint res; vectorint path; // 定义DFS函数 functionvoid(int) dfs [](int start) { res.push_back(path); // 当前路径就是一个子集 for (int i start; i nums.size(); i) { path.push_back(nums[i]); // 选择 nums[i] dfs(i 1); // 递归探索下一层从i1开始避免重复 path.pop_back(); // 撤销选择回溯 } }; dfs(0); return res; }这个解法的时间复杂度是O(2^n)因为每个元素都有选或不选两种可能。空间复杂度主要是递归栈O(n)和存储结果的O(2^n * n)。4.2 网格类问题岛屿问题这类问题通常在一个二维网格grid上进行每个格子可能是陆地‘1’或水域‘0’。DFS用于“淹没”或标记相连的陆地从而统计岛屿数量、计算最大岛屿面积等。核心技巧将二维坐标(r, c)映射为图中的一个节点。从一个陆地格子开始DFS向四个方向上、下、左、右探索并将访问过的陆地标记为水域或其它标记以避免重复计数。// 例题岛屿数量 (Number of Islands) int numIslands(vectorvectorchar grid) { if (grid.empty()) return 0; int m grid.size(), n grid[0].size(); int island_count 0; // 定义DFS函数用于“淹没”一个岛屿 functionvoid(int, int) dfs [](int r, int c) { // 边界条件判断 if (r 0 || r m || c 0 || c n || grid[r][c] ! 1) { return; } grid[r][c] 0; // 标记为已访问淹没 // 向四个方向扩散 dfs(r - 1, c); // 上 dfs(r 1, c); // 下 dfs(r, c - 1); // 左 dfs(r, c 1); // 右 }; for (int i 0; i m; i) { for (int j 0; j n; j) { if (grid[i][j] 1) { island_count; // 发现新岛屿 dfs(i, j); // 用DFS淹没整个岛屿 } } } return island_count; }踩坑提醒网格DFS递归深度可能等于网格中陆地单元格总数对于大型网格如1000x1000全陆地递归版本几乎必然栈溢出。必须使用迭代栈版本。迭代版本中栈里存储pairint,int坐标即可。4.3 图的连通性与路径查找在图论中DFS常用于判断图的连通性、寻找路径、检测环对于有向图和无向图方法不同以及拓扑排序需要配合访问状态标记。判断无向图是否连通从任一节点开始DFS如果能访问到所有节点则连通。寻找两点间路径在DFS过程中记录路径找到目标点时保存或输出。检测有向图中的环使用“三色标记法”0未访问1访问中2已访问。如果在DFS过程中遇到状态为“访问中”的邻居说明存在环。拓扑排序基于DFS的拓扑排序是在节点完成所有后代访问后即递归函数返回前将其加入结果列表头部最终结果列表的逆序即为一个拓扑序。// 检测有向图是否有环邻接表表示 bool hasCycle(int numCourses, vectorvectorint prerequisites) { vectorvectorint graph(numCourses); for (auto p : prerequisites) { graph[p[1]].push_back(p[0]); // 构建图p[1] - p[0] } vectorint visited(numCourses, 0); // 0:未访问, 1:访问中, 2:已访问 functionbool(int) dfs [](int node) - bool { if (visited[node] 1) return true; // 遇到访问中的节点有环 if (visited[node] 2) return false; // 已访问完毕无需再处理 visited[node] 1; // 标记为访问中 for (int neighbor : graph[node]) { if (dfs(neighbor)) return true; } visited[node] 2; // 标记为已访问完毕 return false; }; for (int i 0; i numCourses; i) { if (visited[i] 0 dfs(i)) { return true; // 发现环 } } return false; }5. 性能优化、剪枝与常见陷阱DFS虽然强大但暴力搜索的时间复杂度往往是指数级的。不经优化的DFS在稍大规模的问题面前会寸步难行。因此优化剪枝是DFS高级应用的核心。5.1 剪枝策略减少不必要的探索剪枝的核心思想是在递归树的某个节点如果能够判断从这个节点往下发展的所有分支都不可能产生有效解那么就提前返回不再继续搜索。可行性剪枝当前部分解已经不可能满足问题的约束条件。例如在组合总和问题中如果当前路径的和已经超过目标值就没必要继续添加数字了。最优性剪枝在求最优解如最短路径、最小花费的问题中如果当前路径的代价已经超过了已知的最优解就可以停止。去重剪枝在解空间存在重复状态时避免重复搜索。例如在求数组子集时数组有重复元素需要对同一层中相同的元素进行跳过。// 组合总和II (每个数字只能用一次数组可能有重复) vectorvectorint combinationSum2(vectorint candidates, int target) { sort(candidates.begin(), candidates.end()); // 排序是为了方便去重和剪枝 vectorvectorint res; vectorint path; functionvoid(int, int) dfs [](int start, int sum) { if (sum target) { res.push_back(path); return; } for (int i start; i candidates.size(); i) { // 剪枝1可行性剪枝。如果加上当前数已经超过target由于数组已排序后面的数更大直接break if (sum candidates[i] target) break; // 剪枝2去重剪枝。同一层中如果当前数和前一个数相同则跳过避免重复组合 if (i start candidates[i] candidates[i-1]) continue; path.push_back(candidates[i]); dfs(i 1, sum candidates[i]); // i1因为每个数字只能用一次 path.pop_back(); // 回溯 } }; dfs(0, 0); return res; }5.2 记忆化搜索避免重复计算子问题记忆化搜索是DFS与动态规划结合的产物。当DFS在递归过程中会反复遇到相同的子问题时我们可以用一个缓存通常是哈希表或数组来存储子问题的解。下次遇到相同子问题时直接返回缓存的结果而不是重新计算。典型的例子是斐波那契数列、爬楼梯以及许多网格DP问题如不同路径都可以用带记忆化的DFS来解。// 斐波那契数列 - 记忆化DFS unordered_mapint, int memo; int fib(int n) { if (n 1) return n; if (memo.find(n) ! memo.end()) { return memo[n]; // 直接返回已计算的结果 } int res fib(n-1) fib(n-2); memo[n] res; // 将计算结果存入缓存 return res; }对于网格类DP记忆化搜索的代码往往比自底向上的迭代DP更直观更容易想到。5.3 必须警惕的陷阱与调试技巧栈溢出如前所述这是递归DFS的头号敌人。解决方案预估问题深度深则改用迭代栈或者尝试使用尾递归优化但C标准不保证优化或者增加系统栈空间不推荐不可移植。忘记访问标记或标记时机错误在图遍历中这会导致无限递归和栈溢出。黄金法则在节点入栈或递归调用前时立即标记为已访问。路径恢复回溯不完整在回溯问题中push和popused[i]true和used[i]false必须成对出现且顺序对称。状态复制开销在迭代DFS中如果每次都将整个路径向量复制一份压栈当路径很长时空间和时间开销巨大。优化可以使用一个栈记录操作选择/撤销或者存储父节点指针来回溯重建路径。深度过大导致超时即使不栈溢出深度过大的纯DFS也可能因搜索空间太大而超时。必须结合剪枝或者考虑能否用BFS广度优先搜索解决。调试技巧打印递归树/状态在递归函数入口打印当前深度和状态可以清晰看到搜索过程。使用调试器观察栈在IDE中设置条件断点观察调用栈和局部变量。小数据测试先用极小的、可手动验证的输入测试确保逻辑正确。对比迭代与递归对于复杂DFS可以同时实现递归和迭代版本互相验证结果。6. DFS与BFS的对比与选型DFS和BFS是图遍历的两种基本策略它们各有优劣适用场景不同。特性深度优先搜索 (DFS)广度优先搜索 (BFS)数据结构栈 (Stack)队列 (Queue)遍历顺序深度优先一条路走到底广度优先一层一层向外空间复杂度O(h)h为最大递归深度/图深度O(w)w为图的最大宽度适用场景拓扑排序、检测环、路径记录回溯、解决所有解的问题最短路径无权图、层次遍历、寻找最近解解的特点不一定找到最短路径但可能更快找到某个解能找到最短路径在边权相等时实现复杂度递归简洁迭代稍繁通常用迭代代码模式固定选型指南需要找出所有可能解或问题与“路径”、“排列”相关优先考虑DFS回溯。需要找出最短路径或最少步骤尤其是无权图必须使用BFS。图非常深而宽有限DFS可能更节省内存。图非常宽而深有限BFS可能更节省内存但队列可能很大。检测有向图环或进行拓扑排序DFS更自然。遍历树或图的全部节点两者皆可DFS代码通常更短。在实际面试或开发中经常需要根据问题特点灵活选择甚至结合使用如迭代加深搜索 IDDFS。7. 从理论到实践一个综合案例剖析让我们用一个稍微复杂点的例子来串联所有知识点“单词搜索 II”的简化版。给定一个二维字符板和一个单词判断单词是否存在于板中。单词必须由相邻单元格水平或垂直的字母构成且每个单元格的字母最多只能用一次。这是一个典型的网格DFS回溯问题。bool exist(vectorvectorchar board, string word) { int m board.size(), n board[0].size(); // 方向数组简化代码 vectorpairint, int directions {{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; functionbool(int, int, int) dfs [](int r, int c, int index) - bool { // 终止条件1单词所有字符都已匹配 if (index word.size()) return true; // 终止条件2越界或字符不匹配 if (r 0 || r m || c 0 || c n || board[r][c] ! word[index]) { return false; } // 做出选择标记当前单元格已使用避免重复使用 char temp board[r][c]; board[r][c] #; // 使用一个特殊字符标记 // 向四个方向探索 for (auto dir : directions) { int nr r dir.first; int nc c dir.second; if (dfs(nr, nc, index 1)) return true; } // 撤销选择恢复单元格原状回溯 board[r][c] temp; // 四个方向都走不通返回false return false; }; // 尝试每一个起点 for (int i 0; i m; i) { for (int j 0; j n; j) { if (dfs(i, j, 0)) return true; } } return false; }这个案例体现了DFS回溯的精髓选择将当前格子标记为已使用修改原数组。递归探索基于当前选择向四个方向尝试匹配下一个字母。撤销选择无论成功与否在返回前恢复格子状态以便其他路径可以重新使用它。性能优化点可以在主循环开始前先检查板上的字符是否包含单词中的所有字符如果不包含直接返回false这是一种预处理剪枝。DFS的深度就是单词的长度对于较长的单词递归深度可能达到几十甚至上百。在极端大的棋盘上如果单词也很长递归版本有栈溢出风险。一个健壮的工业级实现可能需要考虑使用迭代栈版本或者对递归深度进行限制和监控。掌握DFS不仅仅是记住模板更要理解其“深入试探与回溯”的灵魂并在不同场景下灵活运用递归与迭代善用剪枝优化。它是你算法工具箱里最值得信赖的探路者帮你系统地探索那些未知而复杂的解空间。

相关新闻

macOS热角功能全解析:从基础配置到高级定制

macOS热角功能全解析:从基础配置到高级定制

1. 热角功能基础解析在macOS系统中,热角(Hot Corners)是一个存在多年却常被忽视的高效功能。这个功能允许用户将鼠标光标移动到屏幕四个角落中的任意一个时,触发预设的系统动作。我最初接触这个功能是在2012年使用MacBook Pro时&a…

2026/10/4 2:16:04 阅读更多 →
iOS激活锁终极绕过:基于applera1n的5步解锁完整方案

iOS激活锁终极绕过:基于applera1n的5步解锁完整方案

iOS激活锁终极绕过:基于applera1n的5步解锁完整方案 【免费下载链接】applera1n icloud bypass for ios 15-16 项目地址: https://gitcode.com/gh_mirrors/ap/applera1n 当您购买了一台二手iPhone,或者忘记了Apple ID密码,面对那个令人…

2026/10/7 2:12:07 阅读更多 →
Windows系统架构与安全机制深度解析

Windows系统架构与安全机制深度解析

1. Windows操作系统架构解析Windows作为全球使用最广泛的桌面操作系统,其核心架构设计直接影响着系统性能和安全特性。现代Windows系统采用混合内核架构,主要包含以下几个关键层次:1.1 硬件抽象层(HAL)HAL作为操作系统…

2026/9/28 19:03:45 阅读更多 →

最新新闻

PPO强化学习实战:用PyTorch让LunarLander稳定突破250分

PPO强化学习实战:用PyTorch让LunarLander稳定突破250分

简介:PyTorch-LunarLander是一个基于PyTorch框架的深度强化学习示例工程,面向想要学习PPO算法的Python开发者,演示如何让智能体在月球着陆器环境中通过策略梯度方法实现自主降落。整个资源压缩包仅5KB,非常轻量,包含4个…

2026/10/11 14:23:29 阅读更多 →
Java 程序员第 44 阶段03:大模型微服务拆分实战,AI 推理服务独立化与 TaoToken 统一接入

Java 程序员第 44 阶段03:大模型微服务拆分实战,AI 推理服务独立化与 TaoToken 统一接入

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:23:29 阅读更多 →
视频生成异步任务查询:Ace Data Cloud与Hailuo Tasks API接入实战

视频生成异步任务查询:Ace Data Cloud与Hailuo Tasks API接入实战

只要接过视频生成类接口,你大概率会遇到同一个困境:提交任务就是一次POST,几秒钟返回一个task_id,看起来一切顺利;可接下来怎么知道视频生成好了没?怎么拿结果?服务端排队要多久?失败…

2026/10/11 14:22:29 阅读更多 →
Cursor规则化配置:用注释驱动AI编程提效

Cursor规则化配置:用注释驱动AI编程提效

1. 项目概述:这不是“配置教程”,而是一套能真正减负的AI编程工作流“Cursor怎么配置才好用?”——这句话背后藏着的,不是对某个软件按钮位置的困惑,而是一个真实、高频、持续消耗开发者心力的痛点:每天花在…

2026/10/11 14:22:29 阅读更多 →
2FSK调制解调系统设计与MATLAB仿真实战:从参数设置到误码率曲线

2FSK调制解调系统设计与MATLAB仿真实战:从参数设置到误码率曲线

简介:一份围绕2FSK(二进制频移键控)调制与解调系统设计与仿真的课程设计文档,基于MATLAB7.0完成,适合通信工程、电子信息类学生作为通信原理课程设计、仿真实验或期末报告的参考资料。文档从设计任务和方案论证出发&am…

2026/10/11 14:22:28 阅读更多 →
深入 vllm-metal 内核:Metal 着色器加速 Paged Attention 与 GQA 的完整指南

深入 vllm-metal 内核:Metal 着色器加速 Paged Attention 与 GQA 的完整指南

【免费下载链接】vllm-metal Community maintained hardware plugin for vLLM on Apple Silicon 项目地址: https://gitcode.com/gh_mirrors/vl/vllm-metal 点击查看 免费下载 vllm-metal 是让 vLLM 在 Apple Silicon 上跑起来的社区硬件插件,它用 Meta…

2026/10/11 14:22:28 阅读更多 →

日新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 10:38:42 阅读更多 →