数据结构与算法
文章平均质量分 81
怎么这么帅啊
这个作者很懒,什么都没留下…
展开
-
【C++】【学习笔记】【二叉树与递归详解与例题】前驱后继问题;染色法递归遍历;最近公共祖先(LCA) 问题
目录六、二叉树与递归1、二叉树天然递归结构2、递归的终止条件 与 递归结构2、较复杂的递归逻辑3、二叉搜索树中的问题参考六、二叉树与递归二叉树是以二叉树定义二叉树的数据结构;天然具有递归性质递归:递归终止条件;递归过程;1、二叉树天然递归结构 104. 二叉树的最大深度 同剑指 Offer 55 - I. 二叉树的深度 递归加深度 111. 二叉树的最小深度dfs int minDepth(TreeNode* root) { if(!root)原创 2021-07-18 14:17:48 · 316 阅读 · 1 评论 -
【C++】【学习笔记】【递归与回溯问题详解与例题】排列问题;组合问题;二维平面回溯;flood fill问题;搜索问题(八皇后);
目录七、递归和回溯1、回溯2、回溯应用 - 排列问题2、回溯应用 - 组合问题3、回溯应用 - 二维平面4、回溯应用 - floodfill算法 问题4、回溯应用 - 搜索问题 - 八皇后参考七、递归和回溯结局问题的思路普遍还是树形问题;写递归的时候,心里要有一个递归树递归调用尝试找答案的问题称作回溯1、回溯 17. 电话号码的字母组合这种题没什么意义,不用复习 O(3^n) = O(2 ^n)指数级;class Solution {public: vector<ve原创 2021-07-18 14:07:08 · 422 阅读 · 1 评论 -
【C++】【学习笔记】【动态规划问题详解与例题】记忆化搜索与暴力穷举思想 ;0-1 背包问题;子序列问题;
目录总框架总目录:九、动态规划问题1、参考练习题2、记忆化搜索与暴力穷举思想的重要性3、0-1 背包问题4、0-1 背包问题- 变种5、0-1 背包问题- 例题6、 最长上升子序列7、 最长上升子序列 -例题7、 最长公共子序列 LCS8、 动态规划找出具体解1、子序列具体解2、0 - 1 背包问题具体解参考总框架总目录:【学习笔记】玩转算法面试-- Leetcode真题分门别类讲解九、动态规划问题经典动态规划问题:斐波那契数列;记忆化搜索:递归的基础上,添加记忆化;自上而下解决问题。动态原创 2021-07-05 12:01:47 · 626 阅读 · 2 评论 -
【C++】【缓存替换策略】【LRU】【LFU 】【FIFO】LRU算法C++实现,并测试;
目录先进先出算法 FIFO ;先进缓存的先被替换最不经常使用算法 LFU ;淘汰最不常使用的字块;额外空间记录字块使用频率;最近最少使用算法 LRU ; 优先淘汰一段时间内没使用的字块;一般使用双链表实现;把当前访问的节点放在表头(淘汰链表尾部);使用双向链表,实现置换算法;实现双向链表:存放key-value、上一个节点指针、下一个节点指针;接口:头部尾部增加节点;弹出头部、尾部节点;删除、增加任意节点;...原创 2021-07-03 21:27:37 · 1514 阅读 · 3 评论 -
【C++】【并查集】并查集实现、模板;并查集基于size、rank的优化;
目录一、引入并查集1、连接问题与路径问题:2、接口二、基础并查集1、 Quickfind模式:1.1、实现2、Quickunion模式:2.1、实现3、Quickunion模式优化:3.1、 Quickunion优化size:3.2、优化size实现3.3、 Quickunion优化rank:3.4、优化rank实现参考一、引入并查集○ 解决连接问题(网络中节点的连接问题)(两个社交网络中的人能不能根据好友互相认识)。○ 数学中的集合类的实现。○ 并查集的高效是因为只回答了连接问题,没有回答路径问题原创 2021-06-29 09:20:00 · 796 阅读 · 1 评论 -
【C++】 【滚动哈希】【Rolling Hash】字符串匹配算法问题; Rabin-Karp 算法;哈希思想;哈希与哈希冲突处理;
目录前言一、问题引入 - 字符串匹配 - 滚动哈希二、滚动哈希 - Rabin-Karp 算法三、代码参考前言哈希是一个思想,将字符串看成高进制的数指,求出其哈希值,用其哈希值解决问题。使用滚动哈希来求解字符串匹配问题就是 Rabin-Karp 算法;一、问题引入 - 字符串匹配 - 滚动哈希其实就是因为暴力法要重复计算好多子问题。那么用哈希来算,就只需要每次选头和尾。 1147. 段式回文字母转成哈希 整形然后取模,不等就直接不用判断,相等在判断哈希冲突的情况。 1392. 最长快乐前缀原创 2021-06-28 16:00:51 · 1390 阅读 · 0 评论 -
【学习笔记】【C++】【Leetcode 分门别类讲解】
目录概述一、时间复杂度分析二、数组问题。概述一、时间复杂度分析图的遍历:邻接表实现 :O(e+V) ;邻接矩阵实现O(e2) ;e为节点数,V为边数。字符串数组,先对字符串排顺序,再将数组按照字典序排序:时间复杂度:O( nslogs+snlogn),因为排序n个字符串+n个字符串的排序(字符串也得遍历一遍)均摊时间复杂度问题:对动态数组的扩容和缩容来说,均摊下去时间复杂度只是O(1);所以造成动态数组的操作,整体的均摊时间复杂度为O(1);但是要注意用lazy resize,避免复杂原创 2021-06-27 22:47:00 · 1359 阅读 · 0 评论 -
【C++】【非比较排序算法】【计数排序】计数排序的稳定性
目录前言一、计数排序1、引入2、更一般的计数排序3、计数排序的稳定性参考前言非比较排序不是说元素之间无法比较。而是说不通过直接比较来排序。常用于字符串的排序过程。一、计数排序计数排序所需要的空间:O(R ) 。R 为数字可能的范围。所以计数排序只适用于小数据范围的排序。是小数据范围,而不是小数据规模。且计数排序是稳定的。> 即,排序元素有多个域,排序前相等的两个元素,排序后位置不变。应用: 学生乘机排序等。1、引入对这类问题的解决:遍历数组,对0、1、2的个数进行统计;然后原创 2021-06-27 10:54:44 · 782 阅读 · 0 评论 -
【C++】【哈希表】【哈希函数】实现自己的哈希表,解决哈希冲突;动态哈希表;
文章目录前言1、哈希表与哈希函数的引入2、哈希表一、设计1、一般、通用哈希函数的设计2、默认哈希函数二、哈希冲突1、链地址法。(seperate chaining )1、1实现1.2、测试2、哈希表的动态空间优化参考前言1、哈希表与哈希函数的引入就像这道题来说,用一个26个的int 型数组,就可以实现对每个字符进行哈希映射。其中哈希函数为:f(char) = char -‘a’ ;哈希表就是那个int [26];这种简单的哈希函数就处理了从键到索引的转换,同时也是简单的一一对应的。而更复杂原创 2021-06-26 15:33:54 · 2332 阅读 · 0 评论 -
【C++】【二叉树】【红黑树】构建RB tree、红黑树 类
文章目录前言1、红黑树定义2、红黑树性能3、红黑树特点一、重点解析1、插入规则1、1、插入节点旁没有红色节点:1、2、插入节点周围有红色节点:2、左旋转、右旋转3、颜色翻转4、插入节点5、析构函数二、完整红黑树类参考前言1、红黑树定义○ 每个节点或是红色,或是黑色。○ 根节点是黑色。○ 每个叶子节点(最后的空节点,和以前的叶子节点概念不一样)是黑色的。○ 红色节点的孩子是黑色的。 任意节点到叶子节点,经过的黑色节点数是一样的。2、红黑树性能完全随机的数据,二分搜索树就很好用了。极端情况会原创 2021-06-25 17:50:57 · 431 阅读 · 2 评论 -
【C++】【二叉树】【AVL 树】构建avl tree 类
文章目录前言一、重点解析1、恢复平衡2、插入节点3、删除节点3、析构函数二、完整AVL tree类参考前言AVL树的引入是为了改造BST 的不平衡性,防止退化为链表。BST 类的构造在文末有链接。AVL树使得其任一节点的左右子树高度差不超过1。平衡性相对宽松。使得其可以有看起来不平衡但却认为平衡的结构。而二叉堆、线段树等平衡二叉树是叶子节点的高度差不超过1。其在插入和删除的时候,都需要从插入、删除节点处向上维护平衡。一、重点解析1、恢复平衡恢复平衡分为了四种情况,分别记为LL、RR、LR原创 2021-06-25 11:14:45 · 479 阅读 · 0 评论 -
【C++】【前缀树】【Trie】前缀树实现,及其使用
目录一、前缀树二、完整代码引用一、前缀树前缀树又称Trie;常用于字典、通讯录的实现。相较于普通的映射:查询与插入的时间复杂度只与单词长度有关。二、完整代码包含了插入、查询、查询前缀;使用map来存next 节点是为了节省空间,以及不仅可以查找单词,还可以查找一些别的字符。同时也可以用泛型来替代char。使得其可以查找其他中文字符之类的。bool型的变量代表,以当前节点为根的单词是否存在。class Trie {private: struct node_trie{原创 2021-06-24 11:21:50 · 444 阅读 · 0 评论 -
【C++】【线段树】线段树实现,及其使用【区间树】
prim一、完整代码二、应用引用一、完整代码#include <cassert>#include <functional>template<class T>class SegmentTree {private: T *tree; T *data; int size; std::function<T(T, T)> function; int leftChild(int index) { r原创 2021-06-18 15:44:18 · 376 阅读 · 0 评论 -
【C++】【手撕】【top K】两个有序数组中第K个数据;(寻找两个正序数组的中位数)
题目描述文章目录题目描述一、思路二、难点:1、中位数:和是奇数和是偶数怎么办三、代码考察的点:一、思路最简单的思路就是从两个数组头/尾开始归并的计数。但是这样时间复杂度0(m+n);并不满足要求。我们利用二分查找 log 时间复杂度的优势。只要单调就能二分即:寻找两个排序数组中第K个数,先从左边取K/2个数,小的那一边的k/2都不可能是第K个数了,于是排除。更新K=k-k/2,也就是在剩下的数组中,找到第 新K的数字。直到K==1,那么取当前还剩余的数组中开头处偏小的。就像上图原创 2021-06-16 23:17:26 · 311 阅读 · 0 评论 -
【C++】【手撕】【top K】两个有序数组间相加和的Topk问题;优先队列、最大堆。
题目描述https://www.nowcoder.com/questionTerminal/7201cacf73e7495aa5f88b223bbbf6d1文章目录题目描述一、思路二、难点:三、代码四、实现:五、更进一步考察的点:一、思路[要求]时间复杂度为O(k \log k)O(klogk)大概能猜出来要用最大堆来实现了。然后再加上用个bfs来扫描周围的最大值。即:将右下角唯一知道的最大值压入最大堆;弹出最大堆中最大的值,这个值就可以加入最终结果中;将这个最大值的左边节点和上原创 2021-06-16 17:28:52 · 1229 阅读 · 0 评论 -
【C++】【二叉树】【二叉搜索树】构建二叉搜索树类。
文章目录一、重点解析1、插入节点2、删除节点2.1、删除最值2.2、删除一般节点3、析构函数二、完整BST类参考一、重点解析1、插入节点插入节点相对简单,只需要判断键值,替换掉相应键值,亦或是创建新的键值。 // 向以node为根的二分搜索树中, 插入节点(key, value), 使用递归算法 // 返回插入新节点后的二分搜索树的根 Node* insert(Node *node, Key key, Value value){ if( node == NULL原创 2021-06-14 15:33:09 · 278 阅读 · 0 评论 -
【C++】【查找算法】二分查找;upper 、lower bound;floor、ceil 等变种问题。【二分总结】
文章目录一、二分查找-basic1. caution:二、upper、lower bound1. caution:2.upper bound3.lower bound二、ceil、floor1. caution:2.ceil2.floor三、相关问题参考一、二分查找-basic时间复杂度 :O(logn);要求:排序数组。1. caution:循环不变量的定义 :// 在arr[l…r]之中查找target循环继续条件: l <= r// 二分查找法,在有序数组arr中,查找targ原创 2021-06-13 12:05:49 · 548 阅读 · 0 评论 -
【C++】【排序算法】归并排序;并的优化、应用插入排序的优化、额外空间的优化、迭代的归并【手撕排序】
文章目录一、归并排序1.优劣2.复杂度分析二、代码1.普通快排2.merge优化+插入排序优化3.额外空间的优化。参考一、归并排序1.优劣相对稳定;即:相同的元素,排之后的次序和排之前的次序一致。需要额外空间;即:在merge 的过程中,需要使用额外的空间。2.复杂度分析空间复杂度为O(n);时间复杂度:因为归并排序递归的将其二分,于是递归的层级就有logn层。具体的是以2为底n的对数。long2 n;每层递归中,都将n个数据都扫描了一次。例如:第二层递归中,堆left-mid原创 2021-06-12 15:13:26 · 537 阅读 · 0 评论 -
【C++】【排序算法】堆排序、构建堆、插入、pop堆顶【手撕最小堆】
文章目录一、最大堆二、最小堆代码1.构建最最小堆类1.1 简单两种排序应用:2.原地堆排序3.最小堆中,用插入排序优化shift 操作参考一、最大堆手撕最大堆在下面链接处,基础知识也有讲,这里就直接贴最小堆的实现。二、最小堆代码1.构建最最小堆类应用较广,适用于TOP K类问题。对于直接排序不是很适合。template<typename Item>class MinHeap {private: Item *data; int count; int capacity;原创 2021-06-10 10:12:37 · 445 阅读 · 0 评论 -
【C++】【排序算法】堆排序、构建堆、插入、pop堆顶【手撕最大堆】
文章目录一、堆排序的意义二、堆排序的应用二、代码1.构建最大堆类1.1 简单两种排序应用:1.2应用:剑指 Offer 40. 最小的k个数2.原地堆排序3.用插入排序优化shift 操作参考一、堆排序的意义构建最大堆,使其堆顶为最大元素。二叉堆为完全二叉树。二、堆排序的应用topK 类问题,通过构建K大小的堆。相较于快排思想,可以实现输入流的topK问题。。。。二、代码1.构建最大堆类应用较广,适用于TOP K类问题。对于直接排序不是很适合。class MaxHeap {pri原创 2021-06-10 09:51:33 · 725 阅读 · 0 评论 -
【C++】【排序算法】快排、双路快排、三路快排【手撕排序】
文章目录一、双路与三路提出的意义排序算法选择:二、代码1.普通快排2.双路快排3.三路快排参考一、双路与三路提出的意义如果包含大量重复元素,paitition会分的不平衡,最差情况退化为O(n2);所以把等于标定点的值均匀分到两边。排序算法选择:大量重复键值选择三路,其余选择两路。三路相较于两路对有重复键值时候优势大得多,但是重复小的反而慢一点,但是总体比两路强。两路与三路都会比归并快。二、代码1.普通快排带重复的,会使其很慢,尽量不要用。template <typename原创 2021-06-09 21:07:28 · 745 阅读 · 0 评论 -
【C++】【最短路径】Bellman-Ford 算法实现(贝尔曼-福特算法)(带负权边的图)【relaxation】
Bellman-Ford一、Bellman-Ford 算法 是什么?1.特点2.思想二、简易实现1.解读2.完整代码参考一、Bellman-Ford 算法 是什么?求解单源最短路径问题的一种算法。它的原理是对图进行V-1次松弛操作,得到所有可能的最短路径。其优于Dijkstra 算法的方面是边的权值可以为负数、实现简单,缺点是时间复杂度过高,高达O(VE)。1.特点Bellman-Ford 支持有负权边的存在。同时能检测出图中有没有负权环算法时间复杂度:O(EV) 其中E为边数、V为节点原创 2021-06-06 11:33:16 · 911 阅读 · 0 评论 -
【C++】【最短路径】Dijkstra 算法实现(迪杰斯特拉算法)【最小索引堆】
Dijkstra一、Dijkstra 算法 是什么?1.特点1.思想二、简易实现1.解读2.完整代码参考一、Dijkstra 算法 是什么?是从一个顶点到其余各顶点的最短路径算法。解决的是有权图中最短路径问题。迪杰斯特拉算法主要特点是从起始点开始,采用贪心算法的策略,每次遍历到始点距离最近且未访问过的顶点的邻接节点,直到扩展到终点为止。1.特点Dijkstra 不支持有负权值边的存在。算法时间复杂度:O(ElogV) 其中E为边数、V为节点数。算法的核心其实是relaxation,松弛原创 2021-06-06 09:54:56 · 553 阅读 · 0 评论 -
【C++】【最小生成树】prim 算法实现(普里姆算法)【最小索引堆】
prim一、prim是什么?1.思想二、简易实现1.解读2.完整代码总结一、prim是什么?普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树。意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (graph theory)),且其所有边的权值之和亦为最小。复杂度分析:E为边数,V为定点数。1.思想使用最小索引堆,且堆大小为节点个数。会及时更新不是横切边的边。遍历当前节点的所有边,看这个边对面的节点。如果对面的没有被遍历原创 2021-06-05 16:05:37 · 1091 阅读 · 0 评论 -
【C++】【最小生成树】KrusKal 算法实现(克鲁斯卡尔算法)。【最小索引堆】【并查集】
KrusKal 一、KrusKal 是什么?1.想法二、简易实现1.代码2.解读参考一、KrusKal 是什么?KrusKal 算法是求连通网的最小生成树的另一种方法。与prim算法不同,它的时间复杂度为O(eloge)(e为边数)。所以,适合于求边稀疏的网的最小生成树。1.想法每次直接在图中,找最小的边。这个最小的边一定最小生成树的一条边。前提是:只要找的边不会使得最小生成树生成一个环。这也是为什么使用并查集的原因。为了使用的边不使得最小生成树构成环。二、简易实现1.代码bobo原创 2021-06-05 09:52:43 · 557 阅读 · 0 评论 -
【C++】【二叉树】二叉树的前、中、后序遍历;迭代、染色法、颜色标记法;
文章目录前言一、颜色标记法二、加强理解1.入栈顺序2. 理解三、引用前言又看了二叉树的遍历的时候,看到了一个大佬的颜色标记法。原文在下面引用处。觉得很有意思,很多经典的迭代方法也是出于这种方法来的。但是颜色标记法,就很容易突破障碍,清晰易懂。一、颜色标记法核心思想如下:使用颜色标记节点的状态,新节点为白色,已访问的节点为灰色。如果遇到的节点为白色,则将其标记为灰色,然后将其右子节点、自身、左子节点依次入栈。如果遇到的节点为灰色,则将节点的值输出。其实只需要一个bool值即可,fa原创 2021-05-29 13:37:30 · 368 阅读 · 0 评论