![](https://img-blog.csdnimg.cn/20201014180756754.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
算法
文章平均质量分 70
神仙别闹
一无所成,一无是处!
展开
-
基于C++实现水仙花数
实际上,可以穷举 0~9 这 10 个数字出现的次数(每个数字都可能出现 0~5 次),当所有数字出现次数之和等于 5 时,说明这时数字的组合有可能为 5 位花朵数,进而求出每个数字的 5 次方分别乘以其出现的次数的和值 sum,再判断 sum 内各个数字出现的次数是否与穷举各个数字时每个数字出现的次数分别相同,若相同,则 sum 就是一个 5 位花朵数。借用这个概念,在程序设计实践中,我们设计了一个程序后,可以在这个程序的基础上,再进行优化和扩展,看能否采用另外的、更好的方法来解决这个问题。原创 2023-11-27 11:07:52 · 4000 阅读 · 0 评论 -
基于C#实现梳排序
下面我们看看具体思想,梳排序有这样一个 1.3 的比率值,每趟比较完后,都会用这个 1.3 去递减 gap,直到 gap=1 时变成冒泡排序,这种算法比冒泡排序的效率要高效的多,时间复杂度为 O(N2/2p) 这里的 p 为增量,是不是跟希尔排序有点点神似。冒泡排序上我们的选择是相邻的两个数做比较,就是他们的 gap 为 1,其实梳排序提出了不同的观点,如果将这里的 gap 设置为一定的大小,效率反而必 gap=1 要高效的多。原创 2023-11-27 11:06:49 · 618 阅读 · 0 评论 -
基于C#实现十字链表
上一篇我们看了矩阵的顺序存储,这篇我们再看看一种链式存储方法“十字链表”,当然目的都是一样,压缩空间。原创 2023-11-27 11:06:09 · 823 阅读 · 0 评论 -
基于C#实现奇偶排序
这篇就从简单一点的一个“奇偶排序”说起吧,不过这个排序还是蛮有意思的,严格来说复杂度是 O(N2),不过在多核的情况下,可以做到 N2 /(m/2)的效率,这里的 m 就是待排序的个数,当 m=100,复杂度为 N2 /50,还行把,比冒泡要好点,因为重点是解决问题的奇思妙想。下面我们看看这个算法是怎么描述的,既然是奇偶,肯定跟位数有关了先将待排序数组的所有奇数位与自己身后相邻的偶数位相比较,如果前者大于后者,则进行交换,直到这一趟结束。然后将偶数位与自己身后相邻的奇数位相比较,如果前者大于后者,则原创 2023-11-27 11:05:29 · 581 阅读 · 0 评论 -
基于C#实现块状链表
这个比较简单,我们在每个链表节点中定义一个 头指针,尾指针和一个数组节点。/// 指向前一个节点的指针/// 指向后一个节点的指针/// 链表中的数组。原创 2023-11-27 11:04:54 · 1102 阅读 · 0 评论 -
基于C#实现鸡尾酒排序(双向冒泡排序)
从结果上面看,我们会发现,当数组有序的时候,我们还会继续往下排,知道完成 length/2 次,这个就跟没优化之前的冒泡排序一样,此时我们可以加上一个标志位 IsSorted 来判断是否已经没有交换了,如果没有,提前退出循环。冒泡是一个单向的从小到大或者从大到小的交换排序,而鸡尾酒排序是双向的,从一端进行从小到大排序,从另一端进行从大到小排序。从图中可以看到,第一次正向比较,我们找到了最大值 9.第一次反向比较,我们找到了最小值1.第二次正向比较,我们找到了次大值8.第二次反向比较,我们找到了次小值2。原创 2023-11-27 11:04:10 · 763 阅读 · 0 评论 -
基于C#实现外排序
我们知道内存队列存放的只是小文件的 topN 条记录,当内存队列为空时,我们需要再次从小文件中读取下一批的 TopN 条数据,然后放入中转站继续进行比较。在这种场景下,我们决定每个文件放 1000 条,也就有 33 个小文件,也就有 33 个内存队列,每个队列取 Top100 条,Batch=500 时刷新。根据实际情况我们来决定到底要分成多少个小文件,并且小文件的数据必须是有序的,小文件的个数也对应这内存中有多少个优先队列。这个基本没什么好说的,采用随机数生成 n 条记录。内存存放量:1200。原创 2023-11-25 11:29:07 · 827 阅读 · 0 评论 -
基于C#实现双端队列
通常情况下,队列的内部都是采用数组来实现,而且带有两个指针 head 和 tail 来指向数组的区间段,为了充分利用数组空间,我们也会用 % 来实现逻辑上的循环数组,如下图。这里有一个注意的细节就是“size 字段“,它是为了方便统计队列是否为满或者队列是否为空。原创 2023-11-25 11:28:35 · 754 阅读 · 0 评论 -
基于C#实现三元组
我们知道矩阵是一个非常强大的数据结构,在动态规划以及各种图论算法上都有广泛的应用,当然矩阵有着不足的地方就是空间和时间复杂度都维持在 N2 上,比如 1w 个数字建立一个矩阵,在内存中会占用 1w*1w=1 亿的类型空间,这时就会遇到 outofmemory。。。那么面临的一个问题就是如何来压缩矩阵,当然压缩的方式有很多种,这里就介绍一个顺序表的压缩方式:三元组。原创 2023-11-25 11:27:37 · 743 阅读 · 0 评论 -
基于C#实现并查集
region 树节点/// 树节点/// 父节点/// 节点的秩#endregion。原创 2023-11-24 10:57:43 · 678 阅读 · 0 评论 -
基于C#实现Kruskal算法
这篇我们看看第二种生成树的 Kruskal 算法,这个算法的魅力在于我们可以打一下算法和数据结构的组合拳,很有意思的。原创 2023-11-24 10:57:08 · 698 阅读 · 0 评论 -
基于C#实现Dijkstra算法
或许在生活中,经常会碰到针对某一个问题,在众多的限制条件下,如何去寻找一个最优解?可能大家想到了很多诸如“线性规划”,“动态规划”这些经典策略,当然有的问题我们可以用贪心来寻求整体最优解,在图论中一个典型的贪心法求最优解的例子就莫过于“最短路径”的问题。原创 2023-11-24 10:56:34 · 904 阅读 · 0 评论 -
基于C#实现线段树
从图中我们可以清楚的看到[0-10]被划分成线段的在树中的分布情况,针对区间[0-N],最多有 2N 个节点,由于是平衡二叉树的形式也可以像堆那样用数组来玩,不过更加耗费空间,为最多 4N 个节点,在针对 RMQ 的问题上,我们常常在每个节点上增加一些 sum,max,min 等变量来记录求得的累加值,当然你可以理解成动态规划的思想,由于拥有 logN 的时间,所以在 RMQ 问题上比数组更加优美。前面我也说了,构建有两种方法,数组的形式或者链的形式,各有特点,我就采用后者,时间为 O(N)。原创 2023-11-23 16:18:58 · 476 阅读 · 0 评论 -
基于C#实现赫夫曼树
赫夫曼树又称最优二叉树,也就是带权路径最短的树,对于赫夫曼树,我想大家对它是非常的熟悉,也知道它的应用场景,但是有没有自己亲手写过,这个我就不清楚了,不管以前写没写,这一篇我们来玩一把。原创 2023-11-23 16:18:28 · 409 阅读 · 0 评论 -
基于C#实现Prim算法
Console.WriteLine("最小生成树为:");Console.WriteLine("最小生成树为:");/// 定义矩阵节点/// 顶点个数/// 边的条数/// 顶点个数/// 边的个数#region 矩阵的构建/// 矩阵的构建//顶点数//边数//构建二维数组i++)//顶点j++)#endregion#region 边的信息。原创 2023-11-23 16:17:58 · 432 阅读 · 0 评论 -
基于C#实现优先队列
我们在每个节点上定义一个level,表示该节点的优先级,也是构建堆时采取的依据。原创 2023-11-22 14:25:51 · 466 阅读 · 0 评论 -
基于C#实现树状数组
有一种数据结构是神奇的,神秘的,它展现了位运算与数组结合的神奇魅力,太牛逼的,它就是树状数组,这种数据结构不是神人是发现不了的。原创 2023-11-22 14:25:20 · 497 阅读 · 0 评论 -
基于C#实现Bitmap算法
在所有具有性能优化的数据结构中,我想大家使用最多的就是 hash 表,是的,在具有定位查找上具有 O(1)的常量时间,多么的简洁优美,但是在特定的场合下:①:对 10 亿个不重复的整数进行排序。②:找出 10 亿个数字中重复的数字。当然我只有普通的服务器,就算 2G 的内存吧,在这种场景下,我们该如何更好的挑选数据结构和算法呢?原创 2023-11-22 14:24:49 · 788 阅读 · 0 评论 -
基于C#实现协同推荐 SlopeOne 算法
// 评分实体类/// 记录差值set;/// 记录评分人数,方便公式中的 m 和 n 的值set;/// 记录打分用户的ID/// 平均值/// 产品类set;set;/// 对产品的打分set;原创 2023-11-21 17:04:19 · 895 阅读 · 1 评论 -
基于C#实现KMP算法
这句话的意思也就是说,在模式 P 中,前 k 个字符与 j 个字符之前的 k 个字符相同,比如说:“abad”的最大前缀真子串为“aba",最大后缀真子串为“bad”,当然这里是不相等,这里的 0<k<j,我们希望 k 接近于 j,那么我们滑动的距离将会最小,好吧,现在我们用 next[j]来记录失配时模式串应该用哪一个字符于 Si 进行比较。= Pj 的时候,我们可以看到满足如下关系式 Si-jSi-j+1…Sn-1=P0P1…若 Pj=Pk2, 则 next[j+1]=k2+1=next[k]+1。原创 2023-11-21 17:03:25 · 300 阅读 · 0 评论 -
基于C#实现AC自动机算法
我要检查一篇文章中是否有某些敏感词,这其实就是多模式匹配的问题。当然你也可以用 KMP 算法求出,那么它的时间复杂度为 O(c*(m+n)),c:为模式串的个数。m:为模式串的长度,n:为正文的长度,那么这个复杂度就不再是线性了,我们学算法就是希望能把要解决的问题优化到极致,这不,AC 自动机就派上用场了。其实 AC 自动机就是 Trie 树的一个活用,活用点就是灌输了 kmp 的思想,从而再次把时间复杂度优化到线性的 O(N),刚好我前面的文章已经说过了 Trie 树和 KMP,这里还是默认大家都懂。原创 2023-11-21 17:02:42 · 333 阅读 · 0 评论 -
基于C++实现循环赛日程表(分治算法)
递归地用这种一分为二的策略对选手进行划分,直到只剩下两个选手时,比赛日程表的制定就变得很简单。据此,将左上角小块中的所有数字按其相对位置抄到右下角,又将左下角小块中的所有数字按其相对位置抄到右上角,这样我们就分别安排好了选手1至选手4和选手5至选手8在后4天的比赛日程。以此类推,我们不难发现,我们可以用分治的方法实现,现自顶向下分解,直到分解到最简单的情况,即人数为2人,这时就可以两两比赛,表的填充为对角填充的方式,然后再自底向上填充表格,具体的看上面的k=1,k=2,k=3时形成的循环表就很好理解了。原创 2023-11-20 11:08:35 · 899 阅读 · 0 评论 -
基于C#实现最长公共子序列
这种方法是最简单,也是最容易想到的,当然时间复杂度也是龟速的,我们可以分析一下,刚才也说过了cnblogs的子序列个数有27个 ,延伸一下:一个长度为N的字符串,其子序列有2N个,每个子序列要在第二个长度为N的字符串中去匹配,匹配一次需要O(N)的时间,总共也就是O(N*2N),可以看出,时间复杂度为指数级,恐怖的令人窒息。不知道大家看懂了没?图大家可以自己画一画,代码完全是根据上面的公式照搬过来的,长度的问题我们已经解决了,这次要解决输出最长子序列的问题,我们采用一个标记函数 Flag[i,j],当。原创 2023-11-20 11:07:43 · 359 阅读 · 0 评论 -
基于C#实现字符串相似度
ABA”和“BBA”的编辑距离为 1,仔细发现我们可以得出如下结论,”ABA“是由 23 个子序列与”BBA“字符串求的的编辑距离集合中取出的最小编辑距离,也就是说在这种情况下我们出现了重复计算的问题,我在求子序列”AB“和”BBA"的编辑距离时,我是由子序列”A“和”BBA“与”B“和”BBA“之间的编辑距离中选出一个最小值,然而序列 A 和序列 B 早之前我已经计算过了,这种重复计算的问题有点像”斐波那契”,正好满足“动态规划”中的最优子结构和重叠子问题,所以我们决定采用动态规划来解决。原创 2023-11-20 11:06:59 · 486 阅读 · 0 评论 -
基于C#实现五家共井
意思就是说五家人共用一口井,甲家的绳子用两条不够,还要再用乙家的绳子一条才能打到井水;丙家的绳子用四条不够,还要再用丁家的绳子一条才能打到井水;丁家的绳子用五条不够,还要再用戊家的绳子一条才能打到井水;上面的公式也就表明了 c 和 h 的比例关系,我们令 h=721k,则 c=148k,将其代入 ⑥,⑦,⑧,⑨,⑩ 可得如下方程组。我们再来看看文艺青年的想法,他们的想法是找 a,b,c,d,e 中的某个数与 h 的对应关系。首先我们看下普通青年的想法,他们的想法是找 a,b,c,d,e 之间的对应关系。原创 2023-11-16 14:22:42 · 143 阅读 · 0 评论 -
基于C#实现猴子偷桃
尾递归中在每次向下递归的过程中,都会将当前层的结果计算出来后向下一层传递,从理论上说,传到下一层后,上一层的参数值已经没有存在的必要了,可以清除上一层中的变量占用的栈空间,那么最终达到的效果就是永远不会出现 StackOverflowException 了,但实际上是否真有这个效果,得要看编译程序是否真的给你优化了。当我们玩转递归的时候,老师说线性递归会将“变量,参数,返回值”在“递”的过程中压栈,如果迟迟“递”不到头的话,栈就会越积越多,最后就爆掉了,window 中系统默认的堆栈空间是 1M。原创 2023-11-16 14:22:11 · 184 阅读 · 0 评论 -
基于C#实现百钱买百鸡
百钱买百鸡的问题算是一套非常经典的不定方程的问题,题目很简单:公鸡5文钱一只,母鸡3文钱一只,小鸡3只一文钱,用 100 文钱买一百只鸡,其中公鸡,母鸡,小鸡都必须要有,问公鸡,母鸡,小鸡要买多少只刚好凑足 100 文钱。由于只有100文钱,则5x<100 => 0<x<20, 同理 0<y<33,那么z=100-x-y,好,我们已经分析清楚了,下面就可以编码了。分析:估计现在小学生都能手工推算这套题,只不过我们用计算机来推算,我们可以设公鸡为 x,母鸡为 y,小鸡为 z,那么我们。令 ②x3-① 可得。原创 2023-11-16 14:21:40 · 186 阅读 · 0 评论 -
基于树 二叉树的回溯搜索算法(DPLL)
注意:既然是递归算法,自然要注意几个重要的点。其中有一个就是要记得你写的递归是否需要回溯。如果需要回溯,那些中间变量以及标记变量都需要及时回溯。(在传指针的时候尤其需要注意!1)全称:Davis-Putnam-Logemann-Loveland。2)思想:基于树/二叉树的回溯搜索算法,主要基于两种策略。原创 2023-11-02 11:03:32 · 298 阅读 · 0 评论 -
A_搜索(A Star)算法
正是这样,启发式搜索对于待搜索的状态会进行不同的优劣判断,这个判断的结果将会对算法搜索顺序起到一种启发作用,越优秀的状态将会得到越高的搜索优先级。上文提到,盲目搜索对于所有要搜索的状态结点都是一视同仁的,因此在每次搜索一个状态时,盲目搜索并不会考虑这个状态到底是有利于趋向目标的,还是偏离目标的。其实上述两种评定方法都只是对当前状态距离目标状态的代价评估,我们还忽略了一点,就是这个状态距离搜索开始的状态是否已经非常远了,亦即状态结点的深度值。的问题,搜索出来的路径所需要移动的步数越少,就越优。原创 2023-10-20 14:56:39 · 1157 阅读 · 0 评论 -
双向广度优先搜索(Bi-Directional Breadth First Search)算法
对于拼图游戏来说,已经知道了开始状态(某个乱序的状态)和目标状态(图片复原时的状态),而这两个状态其实是可以互换的,完全可以从目标复原状态开始搜索,反向推进,直到找出拼图开始时的乱序状态。我们想象一下,让起始于开始状态的树从上往下生长,再让起始于目标状态的树从下往上生长,同时在它们的生长空间中遍布着一个一个的状态结点,等待着这两棵树延伸去触及。要实现双向广搜,并不需要真的用两条线程分别从开始状态和目标状态对向展开搜索,在单线程下也完全可以实现,实现的关键是于让两个开放队列交替出列元素。原创 2023-10-20 14:55:00 · 457 阅读 · 0 评论 -
广度优先搜索(Breadth First Search, BFS)算法
假如我们把所有需要搜索的状态组成一棵树来看,广搜就是一层搜完再搜下一层,直到找出目标结点,或搜完整棵树为止。广度优先搜索是一种盲目搜索算法,它认为所有状态(或者说结点)都是等价的,不存在优劣之分。原创 2023-10-20 14:53:20 · 173 阅读 · 0 评论