- 博客(30)
- 收藏
- 关注
原创 希尔排序 | Shell Sort
当一个元素离它排序后的位置很远时,我们需要移动很多次,从而导致整个算法的效率降低。希尔排序 的思想是允许不相邻的元素的交换。在希尔排序中,我们先使用较大的 h 值对数组进行 h 排序,之后不断减小 h 的值,直到它变为 1。如果每个第 h 个元素的所有子列表都已排序,则称数组是 h 排序的,其中h为子列的长度/间隙。: O(n log(n)),希尔排序的时间复杂度主要取决于区间大小的选择。当给定的数组列表已经排序时,每个区间的比较总数等于给定数组的大小。步骤 2 - 初始化间隙大小的值,即 h 的值。
2022-10-14 22:37:15
229
原创 LRU缓存淘汰算法实现 | LRU Cache
如果所需的页面不在内存中,我们将其加入内存。简单来说,就是在队列的最前面增加一个新节点,并更新哈希表中对应的节点地址。如果队列已满,即所有帧都已满,我们从队列的尾部移除一个节点,并将新节点添加到队列的前端。当一个页面被引用时,需要的页面可能在内存中。如果它在内存中,我们需要将链表的节点分离出来,放到队列的最前面。LRU(Least Recently Used)缓存淘汰算法,可以理解为淘汰。LRU淘汰机制本质上很好理解,但实现起来并不那么容易,尤其是最佳的实现方式?的缓存,是目前应用范围最广的缓存淘汰机制。
2022-09-29 18:22:13
539
原创 如何使用栈来实现队列结构?
堆栈和队列两种最基本的数据结构,相信大部分同学都不陌生,但是你知道如何在不使用编程语言自带的数据结构的情况下,实现自己的队列结构吗?今天就带大家来学习一个最简单的使用两个栈来实现队列结构。设要实现的队列为 q,用于实现 q 的堆栈为 stack1 和 stack2。q 可以通过两种方式实现:(该方法enqueue的复杂度较高):该方法确保最早进入的元素始终位于 stack1 的顶部,因此 dequeue 操作只是从 stack1 中弹出元素。
2022-09-28 20:11:10
498
原创 最小生成树算法 | Prim’s algorithm
因此,在 Prim’s algorithm的每一步,都要找到一个Cut(两组,一个包含 MST 中已经包含的顶点,另一个包含其余顶点),从该Cut中选择最小权重边,并将该顶点添加到MST Set(包含已包含的顶点的集合)。重复之前的操作,选择具有最小键值的顶点,这次我们可以选择7或2,我们选择7(也可以选择2), 所以 mstSet 现在变成 {0, 1, 7}。后,更新0的相邻顶点的键值。键值仅用在尚未包含在 MST 中的顶点,这些顶点的键值表示将它们连接到 MST 中包含的顶点集的最小权重边。
2022-09-27 18:17:33
373
原创 最小生成树算法 | Kruskal’s Minimum Spanning Tree Algorithm
生成树是连通图的子集,其中所有边都是连接的,即可以从任一边遍历到任何边,中间有或没有中间节点。此外,生成树中不得有任何循环。因此我们可以说,如果一个连通图中有N个顶点,那么生成树可能具有的边数为N-1。什么是最小生成树?
2022-09-26 23:33:27
1334
原创 洗牌算法 | Fisher–Yates shuffle Algorithm
算法的思想是从数组的最后一个元素开始,并将其与整个数组(包括最后一个)中随机选择的元素交换,之后在 0 到 n-2 的数组(大小减 1),重复之前的操作直到我们到达第一个元素。最后一个元素到达倒数第二个位置的概率是=(最后一个元素不停留在其原始位置的概率)x(上一个索引选择的概率再次选择 step 以便交换最后一个元素)第 i 个元素到达倒数第二个位置的概率 = (第 i 个元素在前一次迭代中未被选中的概率) x (第 i 个元素在本次迭代中被选中的概率)1:i = n-1(最后一个元素的索引)
2022-09-19 14:58:54
576
原创 字典树 (Trie) | 插入和搜索
如果插入的单词是新的或者是现有词的扩展,我们需要构造新的节点。如果新插入的词是Trie中现有词的前缀,我们只需将这个词的最后一个字母标记为该词的结尾。如果我们将Key存储在二叉搜索树中,平衡良好的 BST 的各种操作的时间复杂度与。成正比,其中 M 是最大字符串长度,N 是树中Key的数量。使用 Trie,我们可以在 O(M) 时间内搜索到Key,但是,Trie 的缺点是对存储要求很高即空间复杂度较高。我们需要将每个键的最后一个节点标记为词节点的结尾。单词的每个字母都作为一个单独的 Trie 节点插入。
2022-09-17 16:39:49
427
原创 最短路径算法 | Bellman-Ford Algorithm
我们在之前的文章中已经讨论了最短路径算法中最经典的。然而,Dijkstra's Algorithm虽然好用,却仍然存在一些缺点即无法解决带有负权重路线的问题,改进后的Dijkstra算法尽管可以解决一些简单的负权重问题,但仍然无法解决带有负循环的图的最短路径问题。为了弥补Dijkstra's Algorithm的缺点,我们需要借用一个适用于任何图的最短路径算法,那就是我们今天要介绍的贝尔曼-福德算法。Dijkstra 算法是一种贪心算法,时间复杂度为 O((V+E)LogV)(使用优先序列改进后)。
2022-09-16 20:39:48
1449
原创 线段树 | Segment Tree
最简单的解决上述问题的方法是常规遍历,但其更新和求和的时间复杂度都是O(n),这显然不是最优的。另一种方法是Prefix Sum的方法,可以在O(1)的时间内得到一个区间的和,但更新操作的时间仍然是O(n)。线段树支持在O(log n + k) 的时间内搜索包含某个点的所有区间,k 是检索到的区间或段的数量。并且每次我们将当前段一分为二(如果它还没有变成长度为 1 的段),然后在分割后的两段上执行相同的操作,对于每个这样的段,我们将其对应的元素总和存储在相应的节点中。一个集合 I 的 n 个间隔的。
2022-09-15 13:56:22
230
原创 二分索引树 | Binary Indexed Tree
例如,在上面的第一个图中(getSum() 的图)中,前 12 个元素的总和可以通过后 4 个元素的总和(从 9 到 12)加上 8 的总和获得元素(从 1 到 8)。将BITree[]数组中所有元素初始化为0,我们需要将我们想要求和的原始数组中的元素按顺序一个个的添加到BITree[]中去,之后想要更新原始数组中的某个元素也可以采用相同的方法,把更新的值和其原来的值的差添加到BITree[]即可, 注意更新操作只对BITree[]有影响。二叉索引树的每个节点存储输入数组的一些元素的总和。
2022-09-14 17:33:06
452
原创 基数排序 | Radix Sort
基于比较的排序算法(合并排序、堆排序、快排等)的上限是 O(nLogn),即它们不能比nLogn 做得更好。计数排序是一种线性时间排序算法,当元素在从 1 到 k 的范围内时,它在 O(n+k) 时间内排序。但如果元素在1 到 n^2的范围内怎么办?我们不能使用计数排序,因为计数排序需要 O(n^2)的时间,这比基于一些比较排序算法要更差。那么我们怎样才可以在线性时间内对这样的数组进行排序吗?答案就是基数排序即Radix Sort。
2022-09-14 11:00:01
227
原创 计数排序 | Counting Sort
计数排序是一种基于特定范围之间的键的排序技术。它通过计算具有不同键值(散列类型)的对象的数量来工作,然后做一些算术来计算每个对象在输出序列中的位置。O(n),其中 n 是元素的总数。
2022-09-08 17:20:13
1563
1
原创 并查集算法(优化) | Union by Rank and Path Compression
在中,我们介绍了Union-Find算法,通过union()和find()操作来检测图中的循环。然而那些操作虽然简单但却并不高效,最坏情况的时间复杂度是线性的即O(n)。这是因为,为了表示子集而创建的树可能是单向倾斜的,并变得像一个链表。假设有 4 个元素 0、1、2、3最初,所有元素都是可以认为是单元素的子集。随着我们不断进行Union()操作,元素之间的关系会变得像一个链表上述情况类似于二叉查找树的极端情况,两者的时间复杂度都是线性的。
2022-09-07 16:53:09
1002
原创 并查集算法 | Union-Find Algorithm
Union-Find Algorithm即并查集算法,常用于解决 动态连通性,判断有向无圈图等问题。根本上讲,Union-Find算法就和他的名字一样是一种对不相交集数据结构执行两个有用操作的算法,不相交集数据结构是跟踪一组元素的数据结构,这些元素被划分为多个不相交(非重叠)子集。在这篇文章中,我们将讨论不相交集数据结构的应用。该应用是检查给定图形是否包含循环。我们跟踪一维数组中的子集,我们称之为 parent[]。以下图为例:对于每条边,用边的两个顶点制作子集。
2022-09-06 20:05:30
688
原创 最短路径算法|Dijkstra‘s Algorithm
最短路径问题几乎是每个计算机专业学生的必学知识点,相关的算法也比较多样,但其中最经典的肯定是由荷兰计算机科学家,1972年图灵奖得主Edsger Dijkstra于1959年发布的Dijkstra's Algorithm。如果值 sptSet[v] 为true,则顶点 v 包含在 SPT 中,否则不包含。数组 dist[] 用于存储所有顶点的最短距离值。最短路径问题简单来说就是给定一个图和图中的一个源顶点,找到从源到给定图中所有顶点的。以下子图显示了顶点及其距离值,仅显示了具有有限距离值的顶点。
2022-09-04 20:13:40
2028
原创 Morris Traversal | 迭代法遍历
树的遍历无论是在考试还是面试中都是一大热点,大多数学生都对普通的递归法中序,前序,后序遍历,以及广度优先法的层次遍历非常熟悉,但不难发现上述方法的空间复杂度其实都是O(n)的(递归会占用内部堆栈),今天就让我们来认识一种全新的迭代的遍历方法 -- Morris Traversal。使用 Morris Traversal,我们可以在不使用堆栈和递归的情况下遍历树。Morris Traversal 的思想是基于Threaded Binary Tree的。
2022-09-03 22:55:32
707
原创 反转链表的常用方法
这是一道经常出现在Leetcode和面试中的链表基础题:给定指向链表头节点的指针,任务是反转链表。例如:如果只是简单的反转链表,我们可以创建一个列表并遍历链表,将遍历的元素储存到列表当中,最后倒序的从列表中提取元素并建立一个全新的链表。然而,这种方法的问题在于需要额外的空间去存储链表中的元素,且至少需要遍历两次(一次储存元素,一次倒序提取元素),这显然不是最聪明的做法。
2022-09-02 17:37:13
448
原创 树的遍历(中序,前序,后序)
与只有一种逻辑遍历它们的线性数据结构(数组、链表、队列、堆栈等)不同,树可以以不同的方式遍历,常见的有中序遍历,前序遍历和后序遍历。实现各种遍历的方法又包括:以上图为例:深度优先遍历:(a)中序(左,根,右):4 2 5 1 3(b)前序(根,左,右):1 2 4 5 3(c)后序(左,右,根): 4 5 2 3 1广度优先或级别顺序遍历:1 2 3 4 5在二叉搜索树 (BST) 的情况下,中序遍历以非递减顺序遍历节点。...
2022-09-01 11:36:40
3777
1
原创 二叉查找树 (BST)| 删除操作
删除操作的最坏情况时间复杂度为 O(h),其中 h 是二叉搜索树的高度。在最坏的情况下,我们可能不得不从根到最深的叶节点。倾斜树的高度可能变成n,删除操作的时间复杂度可能变成O(n)。请注意,只有当被删除节点右子节点不为空时才需要后继节点。在这种特殊情况下,节点的后继为其右子树的最小节点。查找节点的后继节点。将后继节点的复制到被删除节点的位置并删除后继节点。请注意,也可以使用前驱节点。我们只需要将该节点从树中直接删除即可。将其子节点复制到该节点并删除子节点。在这篇文章中,将讨论删除操作。.........
2022-09-01 10:56:01
1441
原创 二叉查找树(BST)|搜索及插入操作
假设我们要搜索数字,我们从根开始,然后我们将要搜索的值与根的值进行比较,如果相等,我们完成搜索,如果它更小,我们知道我们需要转到左子树,因为在二叉查找树中,左子树中的所有元素都较小,而右子树中的所有元素都较大。为了搜索一个值,如果我们有一个排序数组,我们可以通过二分查找法来进行搜索。在二分查找中,我们从搜索空间中的“n”个元素开始,如果中间元素不是我们正在寻找的元素,我们将搜索空间减少到“n/2”,以此类推我们不断缩小搜索空间,直到我们找到想要寻找的值,或者我们将搜索空间缩小到一个元素并停止搜索。.....
2022-08-30 14:23:06
704
原创 平衡二叉树(AVL Tree) | 删除操作
我们在上一篇文章中讨论了 AVL 插入。在这篇文章中,我们将采用类似的方法实现删除操作。删除步骤:为了确保给定的树在每次删除后保持 AVL,我们必须增加标准 BST 删除操作以执行一些重新平衡,和插入操作类似我们根据不同的情况进行以平衡二叉树。设 w 为要删除的节点对 w 执行标准 的BST删除操作。从 w 开始,向上移动并找到第一个不平衡节点。令 z 为第一个不平衡节点,y 为 z 的高度较大的子节点,x 为 y 的高度较大的子节点。注意 x 和 y 的定义与之前的插入操作不同。......
2022-08-29 16:51:30
779
原创 平衡二叉树(AVL Tree) | 介绍及插入操作
AVL 树是一种自平衡二叉搜索树 ( BST ),其中所有节点的左右子树的高度差不能超过一个。上面的树不是 AVL,因为 8 和 12 的左右子树的高度差大于 1。大多数 BST 操作(例如,搜索、最大值、最小值、插入、删除……等)需要时间,其中是 BST 的高度。对于,这些操作的成本可能会变成。如果我们确保在每次插入和删除后树的高度保持为,那么我们可以保证所有这些操作的上限为。AVL 树的高度始终为,其中是树中的节点数。.........
2022-08-29 16:19:33
674
原创 红黑树(Red-Black Tree)- 删除操作
1)执行标准 BST 删除. 当我们在 BST 中执行标准删除操作时(递归删除),最终我们总会删除一个节点,它是一个叶子节点或只有一个子节点(对于内部节点,我们复制后继节点,然后递归调用后继节点的删除,后继节点始终是叶节点或一个有一个子节点的节点)。设 v 为要删除的节点,u 为替换 v 的子节点(注意,当 v 为叶叶节点且 NULL 的颜色被视为黑色时,u 为 NULL)。: 如果兄弟节点是红色,则执行旋转向上移动旧的兄弟节点,重新着色旧的兄弟节点和父节点。新的兄弟将会是黑色的(见下图)。........
2022-08-25 19:05:29
584
原创 红黑树(Red-Black Tree)- 插入操作
目录在上一篇文章中,我们讨论了红黑树的介绍。在这篇文章中,将讨论插入。在AVL 树插入中,我们使用旋转作为工具在插入后进行平衡。在红黑树中,我们使用两个工具来进行平衡。重新着色是节点颜色的变化,即如果它是红色的,则将其更改为黑色,反之亦然。必须注意的是,NULL 节点的颜色始终为黑色。此外,我们总是先尝试重新着色,如果重新着色不起作用,那么我们就进行轮换。下面是详细的算法。根据叔叔的颜色,算法主要有两种情况。如果叔叔(父节点的兄弟节点)是红色的,我们会重新着色。如果叔叔是黑色,我们会进行旋转和/或重新着色。
2022-08-25 19:05:08
508
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人