- 博客(170)
- 收藏
- 关注
原创 前K个高频单词:统计+优先队列
本题是 Top K 问题的变种,核心是自定义排序规则。利用优先队列可以方便地实现按多关键字排序。对于初学者,理解自定义比较器的写法是关键。另外,注意题目中“频率相同按字典序升序”的要求,需要在比较器中正确处理。
2026-04-22 20:51:56
273
原创 二叉树的前序遍历(非递归实现)
二叉树的前序遍历顺序是:根节点 → 左子树 → 右子树。递归实现非常简单,但在实际应用中,递归可能导致栈溢出(树深度较大时),因此掌握非递归版本是必要的。这里给出一种利用栈的迭代实现。
2026-04-22 20:51:40
106
原创 二叉树的后序遍历(非递归实现)
后序遍历的非递归实现需要妥善处理右子树的访问时机。通过增加一个prev指针记录上一次访问的节点,可以有效地判断当前节点的右子树是否已经处理完毕。这种方法代码清晰,易于理解,是面试和工程中的常用写法。掌握了它,二叉树的三序遍历非递归实现就齐全了。
2026-04-20 20:48:17
297
2
原创 【C++】构造函数中调用虚函数:多态失效的陷阱与原理
构造函数中多态失效:在构造函数中调用虚函数,调用的是当前正在构造的类的版本,而不是最终派生类的版本。根本原因对象构造是一个逐步的过程虚表指针在构造过程中逐步更新安全考虑:防止访问未初始化的派生类成员设计启示避免在构造函数中调用虚函数如果需要在对象构造时进行多态操作,使用两阶段构造或工厂模式理解这一特性对于设计安全的继承体系至关重要理解构造函数中虚函数调用的行为,不仅能帮助我们在面试中正确答题,更重要的是能在实际开发中避免潜在的设计陷阱,编写出更安全、更健壮的代码。
2026-04-20 20:48:02
528
1
原创 二叉树的中序遍历(非递归实现)
中序遍历的迭代实现是二叉树遍历的基础模板,理解了这个过程,后续的前序和后序非递归也能触类旁通。关键点在于利用栈保存待处理的节点,并控制访问时机(出栈时访问)。掌握了这个,很多树的题目就能用迭代方式解决了。
2026-04-17 23:39:20
373
原创 二叉树的最近公共祖先:我用栈路径法搞定
二叉树的最近公共祖先问题,核心就是找两条路径的交点。用栈记录路径,然后对齐比较,代码逻辑清晰,不易出错。当然,如果想练递归,也可以尝试另一种经典解法,不过今天先这样啦,我要去刷下一道题了。希望这篇笔记对你有帮助,欢迎评论区交流~
2026-04-17 23:39:10
531
原创 【C++】寻找字符串中第一个只出现一次的字符
频率统计技巧:使用数组或哈希表统计元素出现次数两次遍历策略:第一次统计,第二次查找边界条件处理:空字符串、无唯一字符等情况性能优化:选择合适的算法和数据结构关键要点使用频率统计是解决此类问题的核心思路两次遍历的方法既简单又高效根据具体需求选择合适的字符表示方法注意处理各种边界情况和异常输入掌握这个基本问题不仅能帮助我们在面试中表现出色,还能在实际开发中解决许多类似的问题,如查找第一个重复字符、统计字符频率等。这种"频率统计+顺序查找"的模式是解决许多字符串问题的通用方法。
2026-04-16 22:58:38
324
原创 【C++】私有虚函数与多态:访问权限不影响动态绑定
多态与访问权限无关:虚函数的重写不受访问权限限制编译时与运行时分离:访问权限在编译时检查,虚函数绑定在运行时决定设计意义:允许派生类隐藏实现细节,同时保持多态行为实际应用:常用于模板方法模式、接口实现等场景在C++中,当派生类重写基类的虚函数时,即使派生类中的虚函数是private访问权限,它仍然会覆盖基类中public的虚函数(假设基类虚函数是public)。多态机制是通过虚函数表(vtable)实现的,派生类的虚函数地址会覆盖虚表中对应基类虚函数的槽位。
2026-04-16 22:58:29
552
原创 【C++】LeetCode 606. 根据二叉树创建字符串:详解三种解法与优化技巧
本题的关键在于理解二叉树与字符串的一一映射关系,特别是括号省略的规则。递归法是最直观的解法,适合大多数情况。当树深度较大时,迭代法能避免递归栈溢出的风险。在面试中,建议先讲解递归解法,然后分析括号省略规则,最后如果时间允许,可以讨论迭代法的实现。掌握这道题有助于深入理解二叉树的遍历和序列化问题。
2026-04-15 19:40:53
303
原创 【C++】原地删除有序数组重复元素:两种解法的深度剖析
面试场景:优先展示双指针法,体现算法优化思维小数据量:两种方法都可,erase法代码更直观大数据量:必须使用双指针法工程实践:优先考虑效率和可维护性。
2026-04-15 19:40:34
470
原创 【C++】多重继承中的虚表布局分析:D类对象为何有两个虚表?
B1的虚表包含两个函数0x00bf1348D::func1()(重写B1的虚函数)0x00bf1361(D类新增的虚函数)B2的虚表只包含一个函数0x00bf11ccD::func2()(重写B2的虚函数)在多重继承中,派生类新增的虚函数会被放在第一个基类的虚表末尾。每个基类都有自己的虚表指针派生类对象包含多个虚表指针派生类新增的虚函数被放在第一个基类的虚表末尾其他基类的虚表只包含自己相关的虚函数这个设计既保持了与单一继承的兼容性,又提供了多重继承的灵活性。
2026-04-12 20:45:10
519
原创 【C++】只出现一次的数字 II:位运算的三种解法深度解析
在大多数系统中,int类型是32位需要考虑负数的情况(使用补码表示)我们逐位分析每个数字的二进制表示text状态 ones twos 描述0次 0 0 数字未出现1次 1 0 数字出现一次2次 0 1 数字出现两次3次 0 0 数字出现三次(回到初始状态)位统计法:直观通用,易于理解和扩展状态机法:巧妙高效,体现了位运算的精髓数学方法。
2026-04-12 20:44:41
366
原创 【C++】重载、重写和重定义的区别详解
在同一作用域内,函数名相同但参数列表不同的多个函数。派生类中重新定义基类的虚函数,要求函数签名完全相同。派生类定义了与基类同名的函数,无论参数是否相同,都会隐藏基类的同名函数。重载提供同一功能的不同接口(编译时决定)重写实现运行时多态,是继承体系的核心隐藏往往是无意中造成的错误,需要特别注意正确使用这些特性可以让代码更清晰、更健壮,同时充分利用C++的多态能力。
2026-04-11 15:51:02
837
原创 【C++&string】大数相乘算法详解:从字符串加法到乘法实现
大数相乘算法是计算机科学中的一个基础但重要的问题。模拟手工计算:将复杂问题分解为多个简单步骤算法优化:从简单实现到高效算法的演进边界处理:处理特殊情况如乘数为0、前导零等性能分析:理解不同算法的时间复杂度和空间复杂度关键要点大数相乘可以通过模拟竖式乘法实现使用数组存储中间结果比字符串操作更高效对于非常大的数,Karatsuba或FFT算法是更好的选择正确处理边界情况和进位是算法的关键掌握大数相乘算法不仅有助于解决类似问题,还能提高对算法设计、性能优化和数学思维的理解。
2026-04-11 15:50:44
787
原创 杨辉三角生成算法与C++ vector详解
本题通过杨辉三角的生成,展示了vector在解决二维动态数组问题中的应用。vector作为C++中最常用的容器之一,提供了灵活的动态数组功能。理解其内部机制和正确使用方法是编写高效C++代码的关键。在实际开发中,应根据具体需求选择合适的容器:需要随机访问时选vector,需要频繁在头部插入/删除时选deque,需要键值对映射时选map/unordered_map。
2026-04-09 20:42:44
314
原创 【C++】电话号码的字母组合:从有限处理到通用解法
从特殊到一般:先解决简单情况,再寻找通用规律模式识别:发现组合扩展的通用模式抽象思维:将具体问题抽象为组合构建过程多种解法:同一问题可以有不同解决思路通过这个例子,我们不仅学会了解决电话号码字母组合问题,更重要的是掌握了"组合扩展"这一重要算法思想。这种思想在解决许多其他问题时同样有用,是算法学习中的一个重要里程碑。在实际编程中,我们经常需要从有限的特例开始思考,然后逐步推广到通用情况。这个过程体现了算法设计的精髓:发现问题本质,找到通用规律,实现高效解决。
2026-04-09 20:42:30
445
原创 【C++】反转字符串的进阶技巧:每隔k个字符反转k个
反转字符串的进阶算法展示了如何将简单的字符串反转操作扩展为更复杂的模式处理。分块处理思想:将大问题分解为可处理的小块边界条件处理:正确处理各种边界情况循环步长技巧:使用适当的步长遍历数据原地修改算法:在不使用额外空间的情况下修改数据关键要点以2k为步长遍历字符串每次反转min(k, 剩余字符数)个字符注意处理各种边界条件选择合适的算法实现方式掌握这种字符串处理模式不仅有助于解决类似问题,还能提高对循环、边界条件和算法优化的理解。
2026-04-08 19:05:44
415
原创 【C++】验证回文字符串:高效算法详解与优化
字符串处理:过滤、转换、比较算法设计:双指针、中心扩展等性能优化:时间与空间的权衡边界处理:各种特殊情况关键要点预处理是解决复杂字符串问题的关键步骤双指针法是处理回文问题的核心技巧标准库函数(isalnumtolower)可以简化代码并提高可读性考虑所有边界条件,如空字符串、全符号字符串等掌握回文验证算法不仅是面试的需要,也是实际开发中解决字符串处理问题的基础。通过理解这个问题的各种解法,我们可以更好地应对类似的字符串处理挑战。
2026-04-08 19:05:29
860
原创 【C++&string】寻找字符串中第一个唯一字符:两种经典解法详解
数据结构选择:根据字符集大小选择数组或哈希表时间空间权衡:不同的解法在时间和空间复杂度上的取舍边界条件处理:空字符串、单个字符、全重复字符等情况编码细节:字符编码、索引计算、越界检查等关键要点使用频率统计是解决此类问题的核心思路两次遍历的方法既简单又高效根据具体需求选择合适的字符表示方法注意处理各种边界情况和异常输入掌握这种基本问题不仅能帮助我们在面试中表现出色,还能在实际开发中解决许多类似的问题,如查找第一个重复字符、统计字符频率等。这种"频率统计+顺序查找"的模式是解决许多字符串问题的通用方法。
2026-04-07 20:03:35
616
原创 【C++】巧用静态变量与构造函数:一种非常规的求和实现
这段代码展示了C++的几个重要特性:静态成员变量的生命周期和共享特性构造函数的自动调用机制通过对象数组批量触发构造函数然而,在实际工程中,我们更推荐使用传统的循环、递归或数学公式来实现求和功能,因为:代码意图更清晰性能更好(没有不必要的对象构造)避免静态变量带来的副作用更好的可维护性和可读性这种"花式"实现虽然有趣,但更多的是作为对语言特性深入理解的练习,而非实际应用的最佳实践。记住:优秀的代码应该是简洁、清晰、易于理解和维护的。
2026-04-07 20:03:17
450
原创 【C++】单词反转算法详解:原地操作与边界处理
单词反转算法是一个看似简单但蕴含深度的字符串处理问题。字符串遍历技巧:如何高效地定位和操作子串边界条件处理:空字符串、空格、单个字符等特殊情况原地算法设计:如何在有限空间内完成复杂操作性能优化:减少函数调用、优化内存访问等技巧关键要点使用双指针技术高效定位单词边界原地交换避免额外空间开销正确处理各种边界情况和异常输入根据实际需求选择合适的优化策略掌握这个算法不仅有助于解决类似问题,还能提高对字符串处理、算法设计和性能优化的整体理解。
2026-03-21 22:33:50
525
1
原创 C++队列与优先级队列深度解析:从线性结构到堆结构
让我们回顾自定义queue的实现:cppprivate:public:设计要点适配器模式:queue不是独立容器,而是底层容器的适配器接口转换:将底层容器的转换为队列的push/pop默认容器选择:使用deque而非vector,因为vector不支持O(1)的头部删除让我们深入分析用户提供的priority_queue实现:cppprivate:// 底层容器,存储堆的数组表示public:// 向上调整(插入时使用)
2026-03-21 22:33:36
601
1
原创 【C++】获取字符串最后一个单词长度的多种解法
字符串遍历技巧:从后向前遍历是解决此类问题的关键边界条件处理:空字符串、空格、单个单词等情况都需要考虑算法选择:根据具体需求选择最合适的算法代码鲁棒性:处理各种异常输入情况推荐方法:从后向前遍历法效率高,空间复杂度低代码清晰,易于理解鲁棒性好,能处理各种边界情况掌握这个问题的解法不仅能帮助解决类似问题,还能提高字符串处理的基本功。在实际开发中,根据具体场景选择最合适的方法才是最重要的。
2026-03-18 23:38:03
399
2
原创 深入解析C++容器适配器:stack、queue与deque的实现与应用
容器适配器不是独立的容器,而是设计模式中的适配器模式在STL中的具体实现。它们通过封装已有的容器,提供特定的数据访问接口。cpp// 1. 创建栈// 2. 压栈操作// 3. 查看栈顶// 30// 4. 栈大小// 3// 5. 判断是否为空// No// 6. 弹出元素while (!st.pop();// Yes// 1. 创建队列// 2. 入队操作// 3. 查看队头和队尾// Alice// Charlie。
2026-03-18 23:37:50
536
原创 【C++】字符串中的字母反转算法详解
这个字符串字母反转问题展示了双指针算法在字符串处理中的强大应用。双指针技巧:如何有效地同时从两端遍历和处理数据字符分类:如何判断字符的类型(字母、数字、符号等)原地修改:如何在不需要额外空间的情况下修改字符串边界处理:如何正确处理各种边界情况关键要点使用双指针从两端向中间遍历跳过非目标字符,只处理符合条件的字符确保指针不会越界考虑各种边界情况和特殊输入这个算法简单而高效,是面试中常见的题目,也是实际开发中处理字符串问题的有用工具。掌握这种模式,可以帮助我们解决许多类似的字符串操作问题。
2026-03-17 23:34:15
403
原创 深入解析list:一个完整的C++双向链表实现
这是一个完整的模板类yyq::list的实现,模仿 C++ 标准库中的std::list。作为STL中最经典的双向链表容器,list的实现展示了C++模板编程、迭代器设计、链表操作和内存管理的核心技术。本文将完整分析所有代码,包括被注释的部分,不遗漏任何细节。目录概述一、整体架构与设计1.1 命名空间与头文件保护1.2 链表节点设计二、迭代器设计(核心部分)2.1 第一阶段:两个独立的迭代器类(被注释的初始设计)2.1.1 普通迭代器 list_iterator。
2026-03-17 23:33:56
520
1
原创 【C++】只出现一次的数字 III:位运算的巧妙应用
本题展示了位运算在算法设计中的强大威力。通过巧妙的异或操作和位掩码技术,我们能够在O(n)时间复杂度和O(1)空间复杂度内解决问题。
2026-03-15 23:42:10
300
原创 深入解析vector:一个完整的C++动态数组实现
这是一个完整的模板类的实现,模仿 C++ 标准库中的。作为STL最重要的容器之一,vector的动态数组实现展示了C++模板编程、内存管理和迭代器设计的核心技术。本文将全面分析该实现,不遗漏任何细节。目录概述一、整体架构与设计1.1 命名空间与头文件保护1.2 类成员变量设计二、迭代器与类型定义2.1 迭代器类型定义2.2 迭代器访问函数三、构造函数与析构函数3.1 默认构造函数3.2 拷贝构造函数3.3 指定大小和初始值的构造函数3.4 析构函数四、赋值操作符与交换函数4.1 交换函数。
2026-03-15 23:41:51
578
原创 深入解析string:从设计思想到完整实现
这是一个完整的自定义字符串类的实现,模仿 C++ 标准库中的。代码分为头文件string.h和实现文件string.cpp,采用了现代 C++ 的编程风格和优化技巧。本文将全面分析该实现,不遗漏任何细节。目录概述一、整体架构与设计1.1 命名空间与头文件保护1.2 类成员变量设计二、构造函数与拷贝控制2.1 构造函数2.2 现代拷贝构造(拷贝交换技法)2.3 赋值运算符(拷贝交换技法)2.4 析构函数三、访问接口与迭代器3.1 基本访问接口3.2 索引操作符3.3 迭代器支持四、内存管理策略。
2026-03-11 23:29:33
488
原创 C++日期类设计与实现详解:一个完整的Date类
这个Date类展示了C++面向对象设计和运算符重载的典型应用。通过这个类,我们可以:方便地创建和操作日期对象使用直观的运算符进行日期运算处理日期相关的常见需求虽然有一些可以优化的地方,但这个实现为学习C++类和运算符重载提供了一个很好的范例。理解这个类的设计和实现,对于掌握C++面向对象编程具有重要意义。注意:实际使用中,C++11及以后的标准库提供了<chrono>和日期时间库,建议在项目中使用标准库或成熟的第三方库(如Boost.DateTime)来处理日期时间,这些库经过了充分测试和优化。
2026-03-11 23:29:19
526
原创 基于顺序表的C语言通讯录实现(含数据持久化)
在软件开发中,数据持久化是一个至关重要的功能。今天我们要分析的是一个基于顺序表实现的C语言通讯录程序,它不仅具备了基本的联系人管理功能,还实现了完整的数据持久化机制。这意味着用户的通讯录数据可以在程序关闭后依然保存,下次启动时自动恢复,大大提升了程序的实用性。基于顺序表的通讯录系统设计与实现-CSDN博客,这次是加入了通讯录的文件导入和保存。目录前言正文1. 整体架构设计2. 数据持久化实现数据加载机制数据保存机制3. 初始化与销毁流程智能初始化安全的销毁流程4. 顺序表核心实现动态容量管理高效的数据访问。
2026-03-09 23:02:59
574
1
原创 全面排序算法特性分析与选择指南
没有绝对最好的排序算法,只有最适合特定场景的算法递归与非递归选择递归版本:代码简单,适合中小数据量和开发效率优先的场景非递归版本:性能略优,栈空间可控,适合大数据量和性能敏感场景稳定性需求是选择算法的重要考量因素数据特征(规模、有序程度、类型)直接影响算法性能混合策略往往能获得最佳的实际效果。
2026-03-09 23:02:44
352
原创 二叉树全面解析:从概念到代码实现
二叉树是每个节点最多有两个子树的树结构,通常称为"左子树"和"右子树"。基础概念:二叉树定义、完全二叉树、满二叉树重要性质:节点与边的关系、各类节点数量关系存储结构:顺序存储和链式存储遍历算法:前序、中序、后序、层序遍历统计操作:节点计数、高度计算、第k层节点数查找操作:基于值的节点查找特殊判断:完全二叉树判断内存管理:树的创建与销毁二叉树是数据结构中的重要内容,掌握这些基础操作对于理解更复杂的树结构(如二叉搜索树、AVL树、红黑树等)至关重要。
2026-03-08 23:14:02
774
原创 设计循环队列的链表实现详解
循环链表结构:通过尾节点连接头节点形成环形三指针策略:head、tail、prev 协同工作牺牲空间换清晰:使用 k+1 个节点简化空满判断常数时间复杂度:所有操作都在 O(1) 时间内完成该实现的优雅之处在于它用相对简单的指针操作解决了循环队列的核心问题,特别是通过维护 prev 指针巧妙地解决了链表实现中获取队尾元素的难题。理解这种实现方式对于掌握数据结构的内存管理和指针操作具有重要意义,是学习高级数据结构和系统编程的基础。
2026-03-08 23:13:46
508
原创 平衡二叉树判断的递归解法详解
c// 必须同时满足两个条件:// 1. 高度平衡:|leftHeight - rightHeight| ≤ 1// 2. 子树平衡:左右子树都是平衡二叉树双重递归思维:外层遍历节点,内层计算高度分治思想:将大问题分解为子树平衡性检查条件组合:同时满足高度平衡和子树平衡两个条件虽然当前解法的时间复杂度较高(O(n²)),但它清晰地反映了平衡二叉树的定义。通过后序遍历的优化,可以将时间复杂度降低到 O(n),这体现了算法优化的重要性。
2026-03-07 22:40:08
342
原创 翻转二叉树的递归解法详解
问题本质:翻转二叉树的核心是交换每个节点的左右子树指针递归思维:将大树问题分解为根节点处理+子树处理的子问题指针操作:理解指针交换与值交换的根本区别边界处理:妥善处理空树等边界情况这个问题的经典之处在于它用极其简洁的代码解决了看似复杂的问题,充分体现了"分而治之"的算法思想。掌握这种递归模式对于解决其他树形结构问题具有重要的启发意义。值得一提的是,这个问题因为其在面试中的高频出现和简洁优雅的解法,成为了算法学习中的一个里程碑式的问题。理解并掌握这个问题的解法,是二叉树算法入门的重要标志。
2026-03-07 22:39:52
360
1
原创 二叉树遍历:从前序序列构建与中序遍历
从序列化数据构建树:理解先序遍历的特点,正确处理空节点标记递归算法设计:掌握递归构建树的思维模式遍历算法应用:中序遍历的实际应用解题的关键在于理解先序遍历字符串的结构特点,以及如何通过递归算法准确地重建二叉树结构。这种"序列化-反序列化"的思维模式在树形数据处理中非常重要,是算法学习中的基础技能。
2026-03-06 17:57:42
367
原创 判断子树问题的递归解法详解
子树判断问题的递归解法体现了分治思想和递归组合问题分解:将大问题分解为相同树判断和子树遍历两个子问题递归组合:使用双重递归优雅地解决问题边界处理:妥善处理空树等边界情况subRoot是root的子树当且仅当存在root的某个节点,以该节点为根的树与subRoot完全相同。掌握这种"遍历+比较"的递归模式对于解决其他树形结构匹配问题具有重要意义,是算法学习中必须掌握的核心思维模式之一。
2026-03-06 17:57:32
418
原创 深入理解C/C++程序内存布局:从变量存储位置说起
特点:自动管理、速度快、空间有限、LIFO(后进先出)存储内容:局部变量、函数参数、返回地址等注意事项:避免在栈上分配过大数组(可能导致栈溢出)理解C/C++程序的内存布局是成为优秀C/C++程序员的基础。通过本文的分析,我们可以看到:不同类型的变量存储在不同的内存区域每个内存区域有特定的用途和特点正确的内存管理可以避免许多常见的编程错误掌握这些知识不仅有助于编写更高效的代码,还能帮助调试内存相关的问题,如内存泄漏、野指针、段错误等。记住,清晰的内存管理是编写高质量C/C++代码的关键!
2026-03-05 21:16:53
605
原创 对称二叉树的递归解法详解
问题转化:将整树对称转化为子树镜像对称镜像比较:左-右对应,右-左对应的比较模式递归思维:自顶向下分解,自底向上组合结果该算法的优雅之处在于它直接反映了对称性的定义:一棵树对称当且仅当它的左右子树镜像对称。掌握这种"镜像递归"的思维模式对于解决其他树形结构问题(如翻转二叉树、判断平衡二叉树等)具有重要启发意义。递归解法不仅代码简洁,而且逻辑清晰,是处理树形对称性问题的首选方法。
2026-03-05 21:16:40
556
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅