news 2026/10/28 9:17:23

LeetCode与牛客网C/C++刷题源码:题库结构、环境配置与高频题解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LeetCode与牛客网C/C++刷题源码:题库结构、环境配置与高频题解

简介:基于LeetCode与牛客网题库整理的C/C++设计源码包,面向正在学习C程序设计和C++算法练习的开发者,提供覆盖多类题目的可直接运行、对照学习的代码实现,帮助读者通过实际编码训练夯实指针、结构体、动态内存管理以及面向对象封装、继承与多态等关键知识点。压缩包共40个文件,以24个C语言源文件和14个C++源文件为主,另有1个PNG示意图和1个readme.txt说明文档,整体仅148KB,轻量便于按需取用。每个源码文件对应LeetCode或牛客网上的具体题目,文件名中的日期或编号可用于识别题目批次,适合模仿实现、逐题调试和算法思路复盘;C语言文件题目覆盖基础语法、指针和底层控制,C++文件则展示面向对象与泛型写法,方便对比两种语言的解决思路。目前已有353人浏览学习,适合作为刷题备查、课程设计参考或面试前系统训练的资源。

1. 基于LeetCode与牛客网题库的C/C++设计源码:先解决两个灵魂问题

LeetCode 热门 100 题和牛客网的 C/C++ 题库,是 C 程序设计与 C++ 算法练习绕不开的两座山。我第一遍刷 LeetCode 用的是 Python,图省事,结果到了 C++ 岗位笔试,连vector<int>的返回值都写得磕磕绊绊。后来把这份基于 LeetCode 与牛客网题库整理的 C/C++ 设计源码整个过了一遍,才补上「看得懂题解」和「自己写得出来」之间的缝隙。它解决的是两个很实际的问题:第一,同一道算法题,用 C/C++ 写和用脚本语言写,代码结构差在哪;第二,牛客网那种需要自己处理输入输出的题,和 LeetCode 只填函数签名的题,体例上有什么不同。适合正在冲刺校招笔试、或者想从 Python/Java 切回 C++ 刷题的人。

2. 题库源码的结构拆解:先从文件组织看出一份资源的诚意

我下载这类源码包有个习惯:先看目录结构,再随机打开一个中等难度的题看代码。目录乱成一锅粥、文件名全是1.cpp、2.cpp的资源,大概率是从 CSDN 博客复制粘贴凑出来的,你敢照着学,它就敢坑你。这份源码的目录组织方式是「平台 + 题号 + 解法层级」,LeetCode 按原题号排,牛客网按它的 HJ 编号排,公共数据结构单独拎出来放一边。

2.1 目录与文件命名:按「平台-题号-题名」三级定位

解开压缩包之后,第一层大概是这样的:

C-Cpp-LeetCode-Nowcoder/ ├── LeetCode/ │ ├── 0001_TwoSum/ │ ├── 0005_LongestPalindromicSubstring/ │ ├── ... ├── Nowcoder/ │ ├── HJ001_字符串最后一个单词的长度/ │ ├── ... ├── DataStructure/ │ ├── 链表/ │ ├── 二叉树/ │ └── 栈与队列/ └── README.md

LeetCode 目录里每题一个文件夹,文件夹名是「题号_题名」,题号统一四位补零。这个细节很关键:0001、0002、0010按字符串排序不会乱,如果只写1、2、10,排序后10会跑到2前面,找题的时候很窝火。牛客网目录用 HJ 编号,因为牛客同一个题在 C、C++ 下入口不同,HJ 编号是题库里的稳定标识,用它做目录名不会出现一个题两个名的情况。

每个题目文件夹通常至少两个文件:一个解法cpp文件、一个README.md。多解法的题会放多个 cpp,比如两数之和同时保留暴力枚举和哈希表两个版本,文件名后缀直接标BruteForce、HashMap。我一般找unordered_map的实际写法时,直接搜文件名里带Hash的,不用在几百个main.cpp里逐个翻,这个命名习惯值得抄到自己的刷题仓库里。

2.2 代码规范:一道题的文件打开后长什么样

这份资源统一用类Solution包裹核心解法,函数签名和 LeetCode 原题保持一致。下面是典型文件的骨架,我加了点注释:

#include <vector> #include <unordered_map> using namespace std; class Solution { public: vector<int> twoSum(vector<int>& nums, int target) { // 哈希表记录「值 -> 下标」,边遍历边查 unordered_map<int, int> seen; for (int i = 0; i < (int)nums.size(); i++) { int need = target - nums[i]; if (seen.count(need)) { return {seen[need], i}; } seen[nums[i]] = i; } return {}; } };

有几个刻意设计值得学:一是函数签名直接复制 LeetCode 题面,return {a, b}这种初始化列表写法,在 C++17 标准下不会有歧义;二是for循环里对nums.size()做了(int)强转,避免无符号整型和有符号整型比较时的隐式转换告警;三是用seen.count(need)而不是find之后判end(),少几行代码,语义也更直白,是刷题场景下更舒服的写法。

这种规范性的好处是:你把这道题读熟之后,去 LeetCode 随便挑一道新题,都能猜到这个资源包里对应文件长什么样,不需要重新适应一套代码风格。源码包里README.md还附了题目链接和复杂度分析,这比我见过很多只有代码没有说明的资源实用得多。

2.3 难度与考点分布:先刷哪些题收益最大

平台主要覆盖范围高频考点
LeetCode 0001-0100入门到中等哈希表、双指针、链表、二叉树、动态规划
牛客网 HJ001-HJ100校招机考高频字符串处理、排序、进制转换、多组输入输出
DataStructure 目录复用组件链表反转、二叉树遍历、栈与队列

我拿到手之后先按考点刷而不是按题号刷。哈希表和双指针是性价比最高的两类,因为它们是后续滑动窗口、前缀和、链表类题目的地基;二叉树题目适合用来练递归,C++ 写递归时传引用和返回值的取舍,只有亲手写够二十道才有感觉。牛客网的 HJ 段题目更贴近实际机考,很多题要求写完整main函数加scanf读入,和 LeetCode 纯函数式刷题完全是两套手感,后面单独讲。

3. 把环境调到能直接跑:VS Code 配置 C/C++ 的四个关键文件

源码拿到手,第一件事不是打开题目,是先把编译调试环境跑通。我见过太多人在这一步翻车:g++装了一半、头文件路径不对、F5之后根本没有 debug 选项。这套资源本身不带编译器,你需要自己准备一个能编译 C++11/17 的环境,我用的是 Windows 下 MSYS2 加 VS Code 的组合,Linux 和 macOS 用户直接用系统g++即可。

3.1 编译器选型与安装:为什么选 MinGW-w64

LeetCode 和牛客网题解代码,绝大多数场景只需要标准库,不需要任何平台特定的头文件。所以编译器只要满足两个条件就行:支持 C++17、能搭配 GDB 调试。Windows 上我推荐 MSYS2 而不是老的 TDM-GCC,因为 MSYS2 的包更新及时,GDB 也一并维护。装好后在终端执行:

pacman -S mingw-w64-ucrt-x86_64-gcc mingw-w64-ucrt-x86_64-gdb

装完验证一下版本,g++ --version能输出说明环境变量没问题。如果不想用 MSYS2 的终端,手动把C:\msys64\ucrt64\bin加到系统 PATH 里。这里有个常见误区:MSYS2 有mingw64和ucrt64两套运行库,我个人习惯用ucrt64,它对 UTF-8 源码的支持省去很多乱码麻烦。Linux 用户直接用sudo apt install g++ gdb,macOS 用户用xcode-select --install带的clang++,本资源代码在 clang 下编译也不会有兼容性问题,因为全程没用 GCC 私有扩展。

3.2 c_cpp_properties.json:让 IntelliSense 不再满屏报红

VS Code 打开源码根目录后,如果红色的波浪线比代码还多,八成是c_cpp_properties.json没配对。用 Ctrl+Shift+P 搜「C/C++: Edit Configurations」,生成并改成这样:

{ "configurations": [ { "name": "Win64", "includePath": [ "${workspaceFolder}/**" ], "compilerPath": "C:/msys64/ucrt64/bin/g++.exe", "cStandard": "c17", "cppStandard": "c++17", "intelliSenseMode": "windows-gcc-x64" } ], "version": 4 }

includePath里的${workspaceFolder}/**表示把整个工作区所有子目录都加入索引,这样源码里自定义的头文件能直接被识别。compilerPath一定指向你实际装的编译器路径,写错的话 IntelliSense 会退回默认模式,unordered_map都能给你标红。cppStandard显式指定 C++17,编辑器提示的语法检查标准就和编译命令保持一致,不会出现这边代码提示报错、那边g++却能编过的精神分裂局面。

3.3 tasks.json 与 launch.json:Ctrl+Shift+B 编译,F5 调试

编译和调试是两套任务,需要两个 JSON 文件配合。先配置tasks.json,它负责一键编译当前打开的文件:

{ "version": "2.0.0", "tasks": [ { "label": "g++ compile single file", "type": "cppbuild", "command": "C:/msys64/ucrt64/bin/g++.exe", "args": [ "-std=c++17", "-g", "-O0", "-finput-charset=UTF-8", "${file}", "-o", "${fileDirname}/${fileBasenameNoExtension}.exe" ], "options": { "cwd": "${fileDirname}" }, "group": { "kind": "build", "isDefault": true }, "problemMatcher": ["$gcc"] } ] }

args里每一项都是踩过坑补上的:-g生成调试信息,没有它 GDB 看不到源码行号;-O0关闭优化,否则变量被优化后调试时显示optimized out;-finput-charset=UTF-8让源码里的汉字注释在中文 Windows 下不乱码。${file}是当前活动文件的绝对路径,${fileBasenameNoExtension}是去扩展名的文件名,这样每次编译生成的可执行文件和源文件同目录同名。

然后是launch.json,F5 时先执行上面的编译任务,再用 GDB 拉起可执行文件:

{ "version": "0.2.0", "configurations": [ { "name": "gdb debug", "type": "cppdbg", "request": "launch", "program": "${fileDirname}/${fileBasenameNoExtension}.exe", "args": [], "stopAtEntry": false, "cwd": "${fileDirname}", "environment": [], "externalConsole": false, "MIMode": "gdb", "miDebuggerPath": "C:/msys64/ucrt64/bin/gdb.exe", "preLaunchTask": "g++ compile single file" } ] }

preLaunchTask的值必须和tasks.json里label完全一致,大小写都不能错,很多人调试按钮是灰的就是这里没对上。externalConsole设成false,程序输入输出走 VS Code 的集成终端,比弹出来的黑窗口方便截取输出。这套配置针对的是「单文件刷题」场景,如果你手里是多文件工程,tasks.json里要把${file}换成显式列出的全部.cpp,或者改用 CMake 来管,那是另一种玩法了。

3.4 命令行快速验证:不想开 VS Code 时的备选路径

不是每次刷题都要开编辑器,文件多了之后我更习惯命令行直接验证一道题对不对:

g++ -std=c++17 -g -O0 -Wall Solution_HashMap.cpp -o solution ./solution

-Wall把常见警告全部打开,有些隐藏 bug 在运行前就被编译器提醒了。这份源码每个题的文件都是自包含的,只有一个题解文件时可以直接这样编;如果文件里只写了class Solution没有main,我会临时在文件末尾追加一个测试main,或者在另一个测试文件里 include 它再编译,命令行方式跑通后再把测试代码删掉,保证提交到平台时函数签名干净。

4. 三个高频题解的复现:从哈希表到中心扩展

环境配好之后,我建议先用三个高频典型题把这份源码的解题思路走一遍:两数之和、最长回文子串、反转链表。这三个题分别代表哈希表查值、双指针边界利用、链表指针操作,是刷题的第一批「模型题」,后面的题目大量是这三个模型的变体,把它们的 C++ 写法吃透比盲目刷五十道新题更有用。

4.1 两数之和:暴力解到哈希表的复杂度跃迁

两数之和的思路本身谁都懂,但 C++ 实现里有个隐藏考点:返回下标的顺序。暴力解就是两层循环:

#include <vector> using namespace std; class Solution { public: vector<int> twoSumBruteForce(vector<int>& nums, int target) { int n = nums.size(); // 外层固定第一个数,内层找第二个数 for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { if (nums[i] + nums[j] == target) { return {i, j}; } } } return {}; } };

内层从i + 1开始搜,保证了返回的i < j,避免同一对元素被正反数两次。时间复杂度O(n^2),在 LeetCode 上数据量一大就超时,所以它存在的意义只是为了和哈希版对照理解复杂度。哈希版题目里要求「不能重复用同一个元素」,所以seen[nums[i]] = i放在检查之后,当前元素不会在本次迭代里被自己匹配到,这个顺序写反了就会返回{i, i}这种错误答案。

#include <vector> #include <unordered_map> using namespace std; class Solution { public: vector<int> twoSum(vector<int>& nums, int target) { // 哈希表记录「值 -> 下标」,每次先查 need 是否已出现 unordered_map<int, int> seen; for (int i = 0; i < (int)nums.size(); i++) { int need = target - nums[i]; if (seen.count(need)) { return {seen[need], i}; } seen[nums[i]] = i; } return {}; } };

unordered_map是 C++11 引入的哈希表,插入和查找平均 O(1),所以整体复杂度降到 O(n)。和map相比它的元素无序,但是刷题场景绝大部分题目不要求按下标顺序输出哈希表的键,所以优先用unordered_map,不要因为教科书上先教map就默认选它,性能差一个量级。

4.2 最长回文子串:中心扩展法的边界处理

这个题我最早是用动态规划写的,二维vector<vector<bool>>跑起来没问题,但空间复杂度 O(n²),而且初始化dp[i][i] = true那一段很容易写着写着边界错乱。中心扩展法更省空间,也更符合 C++ 的字符串操作习惯:

#include <string> #include <algorithm> using namespace std; class Solution { public: string longestPalindrome(string s) { int n = s.size(); if (n < 2) return s; int start = 0, maxLen = 1; for (int i = 0; i < n; i++) { // 奇数长度的回文中心是单个字符 int len1 = expandAroundCenter(s, i, i); // 偶数长度的回文中心是两个字符之间 int len2 = expandAroundCenter(s, i, i + 1); int len = max(len1, len2); if (len > maxLen) { // 回文长度 len 对应左边界 = i - (len-1)/2 start = i - (len - 1) / 2; maxLen = len; } } return s.substr(start, maxLen); } private: int expandAroundCenter(const string& s, int left, int right) { // 向两边扩展,只要左右字符相等就继续 while (left >= 0 && right < (int)s.size() && s[left] == s[right]) { left--; right++; } // 循环退出时 [left+1, right-1] 是最大回文,长度 = right-left-1 return right - left - 1; } };

核心是expandAroundCenter的返回值:循环结束后left停在回文串外一格,right也停在回文串外一格,所以长度是right - left - 1。这个公式记不住的话随便找一组例子推一遍就知道错不了。另一个容易错的地方是start = i - (len - 1) / 2:len是偶数时比如len=4,中心i在中间偏右的位置,减(len-1)/2=1正好到左边界;len=3时(len-1)/2=1,减完也在左边界。把-1删掉,偶数长度回文就会整体错一位,这是这道题最阴间的边界。

4.3 反转链表:迭代和递归两套写法对照

链表题在牛客网机考里出现频率极高,因为需要自己定义结构体、处理空指针和尾节点。迭代版是很典型的双指针:

#include <cstddef> struct ListNode { int val; ListNode* next; ListNode(int x) : val(x), next(NULL) {} }; class Solution { public: ListNode* reverseList(ListNode* head) { ListNode* prev = NULL; ListNode* cur = head; while (cur != NULL) { ListNode* next = cur->next; // 先把后继存下来 cur->next = prev; // 当前节点指针反转 prev = cur; // prev 后移 cur = next; // cur 后移 } return prev; } };

每一步的变量跟着注释走,next必须在修改cur->next之前保存,否则链表后半段断掉找不回来。循环结束后prev指向原链表的尾节点,也就是新链表的头。递归版更短,但理解起来绕一点:

class Solution { public: ListNode* reverseList(ListNode* head) { if (head == NULL || head->next == NULL) return head; // 递归反转后面所有节点,返回新头 ListNode* newHead = reverseList(head->next); // 此时 head->next 已经是反转后的尾节点 head->next->next = head; // 让尾节点指向当前节点 head->next = NULL; return newHead; } };

递归的出口条件head == NULL || head->next == NULL一次性处理了空链表和单节点链表两种情况。有的题解在head->next上没有判空,递归深度到最后一个节点时会空指针解引用崩溃。实际机考我两种都会写:时间紧优先迭代,因为边界清晰不容易错;面试官追问逆序思想时再补递归版,说明你两种思路都通。

4.4 牛客网体例:多组输入输出和 LeetCode 最大的差异

LeetCode 给你一个填好参数空壳的函数,你不用管输入输出,平台自动调度。牛客网很多校招题是 ACM 风格,要自己从标准输入读,而且同一组数据可能连续输入多行,直到 EOF 才结束。这份源码里华为机试题基本都是这种模式,典型的骨架:

#include <cstdio> int main() { int n; // 持续读到文件末尾,注意这里不是 if 而是 while while (scanf("%d", &n) != EOF) { long long sum = 0; for (int i = 0; i < n; i++) { int x; scanf("%d", &x); sum += x; } printf("%lld\n", sum); } return 0; }

while (scanf("%d", &n) != EOF)处理的是「多组测试数据」场景,平台会把所有测试用例通过标准输入一次性喂进来,你每成功读一组就输出一组答案。很多人写成if只读一次,第一组数据跑完程序就结束了,后续用例直接判错。还有printf里的%lld对应long long,避免加法溢出。本地自己测试的时候,输完一行数据按Ctrl+D(Linux)或Ctrl+Z然后回车(Windows)模拟 EOF,就能验证多组循环的逻辑对不对。

5. 刷题避坑手册:本地能跑、提交报错的五个血泪原因

下面这几条是我把这份资源里的代码在 LeetCode、牛客网上实际提交过程中踩出来的坑,每一条都对应一个真实的失败提交记录。按「现象、原因、解决」写,遇到同样问题直接对号入座。

5.1 现象:本地 VS Code 编译通过,提交 LeetCode 报编译错误

原因:VS Code 里tasks.json指定了-std=c++17,但 LeetCode 老题目的代码环境是 C++11,你用了 C++17 特性比如结构化绑定auto [a, b] = ...、std::clamp,本地编译自然没问题,提交上去编译器不认识。解决:写完代码后自查三件事——没用std::optional、没用if (auto it = map.find(x); it != map.end())这种带初始化的 if、for循环里没有用auto [k, v]解构pair。这份源码里绝大多数代码只用到 C++11 特性,但你自己把unordered_map换成map之类的操作,就可能顺手用上新标准特性。稳妥起见,提交前跑一遍:

g++ -std=c++11 -Wall -Wextra Solution.cpp -o /dev/null

能编过再去粘贴。

5.2 现象:牛客网题目要求按下标顺序输出,用map结果全乱

原因:std::map内部是红黑树,迭代顺序按键升序,不按插入顺序。如果是求数组「找出重复数字并按下标从小到大输出」,map会输出键排序后的结果,和题目要求对不上。解决:审题两务必——第一,题目不说排序一律假设要和原数组顺序一致;第二,需要「按插入顺序遍历」时用unordered_map加一个vector记录插入顺序,或者直接改成vector暴力扫。这份源码里凡是哈希解法都会在注释里写明输出顺序的假设,你抄的时候别把注释删了。

5.3 现象:牛客网while(scanf("%d", &n))死循环,终端里输入多少组都不结束

原因:scanf返回值是成功读取的变量个数,不是是否到达 EOF。输入流一旦读到非数字内容,scanf返回 0,while(0)不会跳出循环;只有到达文件末尾返回EOF程序才停。如果在 Windows 终端里只按回车,永远不会产生 EOF。解决:写while (scanf("%d", &n) != EOF),本地想结束输入就按Ctrl+Z再回车。另外注意%d和%c混用时,%c会吃掉前一个输入后的换行符,导致读入的char全是\n,这种情况在%d后加一个getchar()把换行吞掉。

5.4 现象:GDB 调试时变量窗口显示optimized out,断点打上了但看不了值

原因:tasks.json的args里如果漏了-O0或者手动编译时用了-O2,编译器会把局部变量优化掉,调试信息里缺失这个变量。解决:调试用的编译命令必须带-g -O0,发布时才用优化。VS Code 里配好第 3 章的tasks.json后,重新用Ctrl+Shift+B编译一次再按 F5,变量窗口就能正常显示了。这条我吃过两次亏,一次是在一个for循环里想查i的值,结果被优化进寄存器,窗口一片红。

5.5 现象:LeetCode 上链表题提交通过率低,本地测[1,2,3]反转后正常,提交就AddressSanitizer报错

原因:你在修改cur->next时没有保存next节点,导致链表断了之后访问到野指针;或者head->next->next = head在递归版里对空指针解引用。LeetCode 提交时会开内存检测,本地跑一两次可能侥幸没崩,大数据量用例下必炸。解决:链表操作三原则——改指针前先备份、移动指针前判空、递归函数先写出口条件。照第 4.3 小节的顺序,把next = cur->next放在最前面执行,写完整后自己在本地测一遍[]、[1]、[1,2]、[1,2,3]四种用例再提交,这四种边界过了基本不会有内存问题。

6. 把题解变成自己的:模板化刷题与变体识别

源码刷到一半,我最大的体会是:能记住的题解代码都是「模板」,记不住的都成了「似曾相识」。所以从这份资源开始,我每读完一类题,就把它浓缩成一个模板文件,存进自己单独的仓库里。比如双指针模板:

// 双指针模板:有序数组里定位一类满足条件的组合 bool twoPointerTemplate(vector<int>& nums, int target) { // 前提:nums 已升序,否则先排序 sort(nums.begin(), nums.end()); int left = 0, right = (int)nums.size() - 1; while (left < right) { int sum = nums[left] + nums[right]; if (sum == target) return true; else if (sum < target) left++; // 和太小,右移左指针 else right--; // 和太大,左移右指针 } return false; }

模板化之后,再遇到「容器盛水」「三数之和」「最接近的三数之和」这些题,先把它们拆成「排序 + 双指针」这个骨架,再按题目条件改内层逻辑。真正看懂一道题,不是能写出官方题解,而是能说清楚它属于哪个模板、和模板差在哪——是判断条件变了,还是指针移动规则变了,又或是需要额外维护一个哈希表。

从那以后,我每次新建刷题工程,都强制先把环境配置和模板文件放进仓库,再开始动题目代码。这个习惯救了我好几次:换电脑、重装系统,都能在两小时内恢复到前一天的状态,不用重新配编译器路径。这份资源的价值不只是那几百道题的答案,而是它提供了一个标准化的代码组织方式,你可以直接把它当仓库骨架用,在它的目录里继续添加自己的新题解。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/28 9:16:56

RM3100地磁传感器实战:从手册到驱动到PCB校准避坑指南

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

作者头像 李华
网站建设 2026/10/28 9:16:45

Codex 进化史:从代码补全到软件工程智能体

1. 从"补全代码"到"接活干项目"&#xff1a;Codex这一路到底变了什么聊 Codex 之前&#xff0c;得先说一个很多人都有的误解&#xff1a;以为它就是一个更聪明的代码补全工具&#xff0c;放进 IDE 里写注释、续写函数、生成单元测试就完事了。早在 2021 年…

作者头像 李华
网站建设 2026/10/28 9:13:41

UEFI开机图标替换实战:HackBGRT安装、配置与救砖

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

作者头像 李华
网站建设 2026/10/28 9:13:38

JavaWeb图书馆管理系统源码:JSP+Servlet+JDBC借阅实战

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

作者头像 李华
网站建设 2026/10/28 9:13:00

汽车电子底层软件中的数学:从ADC标定到PID与CRC

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

作者头像 李华
网站建设 2026/10/28 9:12:26

YOLOv5训练DNF识别模型:自动脚本目标检测避坑指南

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

作者头像 李华