王晓东数据结构
小胡同的诗
千里之行,始于足下
展开
-
【算法设计与分析】算法的时间复杂度(介绍O渐近上界,Ω渐近下界,θ准确的界)
什么是时间复杂度?我们先看看一些函数的渐近表达式:关于时间复杂度的基本要点:时间复杂度反映的是随着问题规模的变大,计算所需的时间的增长速度,与系数的多少关系不大算法的渐近时间复杂度,简称时间复杂度,很多时候为了便于理解,直接把时间复杂度等同于O()是可以的。常见的时间复杂度,及其增长速度比较:O(1)<O(log2n)<O(n)<O(nlog2n)<O(n2)<O(n3)<O(2n)<O(n!)<O(nn)O(1)<O(log_2n)<O(n)<O(nlog_2n)<转载 2020-10-16 10:16:13 · 11132 阅读 · 1 评论 -
求顺序表中最大值和次大值的最优算法
问题描述给一个 n 个数字的顺序表,求其中的最大值和次大值。求一个比较次数不大于 n−⌈logn⌉−2n-\lceil logn \rceil-2n−⌈logn⌉−2 的算法。算法顺序比较初始化最大值和次大值是下标为 0 的元素,之后每次更新最大值时,把上次最大值给次大值;不能更新最大值时也要和次大值比较看能否更新次大值。易得最坏情况下比较次数为 2(n−1)2(n-1)2(n−1)。堆我们发现,堆的结构可以在常数时间内找到最大值和次大值。但是在构建堆的时候,每次调整的比较次数约为 2h2h2h原创 2020-09-16 00:16:11 · 3576 阅读 · 0 评论 -
求顺序表中最大值最小值的最优算法
题目描述给一个 n 个数字的顺序表,求其中的最大值和最小值。求一个比较次数不大于 ⌈3n/2⌉−2\lceil 3n/2 \rceil-2⌈3n/2⌉−2 的算法。思路顺序查找首先最大、最小值初始化为第一个数,对于之后的数我们都进行比较更新。易得最坏情况下比较次数为 2n−32n-32n−3 。实现见代码 f0 部分。分组比较我们可以预处理数组:每两个数字划成一组,较小的放前面,较大的放后面。于是,最小值就可以从前面的数字中获取,最大值从后面的数字获取。比较次数计算如下:复杂度符合要求。实现见原创 2020-09-15 22:28:41 · 4566 阅读 · 0 评论 -
5.2.5 三数取中划分快速排序算法
前言每次选三个数(第一个、最后一个、倒二个),以到二个作为中位数进行分治排序#include <bits/stdc++.h>using namespace std;#define ElemType int#define M 10ElemType arr[1000005], arr2[1000005];int vis[1000005];void SelectSort...原创 2019-09-11 15:18:21 · 740 阅读 · 0 评论 -
5.2.6 三划分快速排序算法
前言当数组中有大量重复的元素时用三划分可以有效地提升效率,并且当数组中没有大量重复元素时该算法的效率也不低于原快速排序的效率思路将整个数组分成三份,也就是找两个分界点,我们假设分界点l,r满足l<r,则中间有r−l个等于v的元素,左右分别为小于v和大于v的元素将整个数组分成三份,也就是找两个分界点,我们假设分界点l,r满足l<r,则中间有r-l个等于v的元素,左右分别为小于v和...原创 2019-09-25 11:29:43 · 904 阅读 · 1 评论 -
7.8 DAG上的多源最短(长)路径问题(动态规划)
目录前言图模型算法DAG最短路描述实现DAG最长路描述实现DAG所有顶点对之间的最短路描述实现抽象图模型二维矩形嵌套分析思路1(转为DAG上最长路)思路2(转为LIS问题)硬币问题思路完全背包比较记忆化搜索递推打印路径补充n维矩形嵌套问题总结前言首先要知道什么是DAG,有向无环图,可以求拓扑排序,关键路径,在工程规划上有很大的用处。如果发现某个问题给的前提是DAG,那么,根据DAG的无圈性,...原创 2019-09-04 13:56:17 · 1511 阅读 · 0 评论 -
11.5 左偏树总结(可并斜堆)
目录前言定义性质实现左偏树结构合并堆操作完整代码前言可并堆有多种方法实现,例如斐波那契堆,配对堆等,以下记录左偏树,也称为斜堆。是一种基于非平衡二叉树的数据结构,其在合并堆的时候可以达到O(log(m+1))O(log(m+1))O(log(m+1))的速度。当然,左偏树还分好几种,如左偏高树左偏重树等。关于左偏,实际上就是让左子树的特征数量不小于右子树,例如左偏高树就是左子树的高度不小于右...原创 2019-09-17 10:40:09 · 653 阅读 · 0 评论 -
应用举例2.9 Josephus排列问题
问题描述:思路:用循环链表模拟用数组游标模拟动态规划(数学方法)设dp[i]dp[i]dp[i]表示剩余i个人进行出环的最终胜利者,显然可以得到一个状态转移方程:dp[n]=(dp[n−1]+m)dp[n]=(dp[n-1]+m)%ndp[n]=(dp[n−1]+m)。相当于从1个人去推出n个人的递推关系。复杂度O(n)O(n)O(n)当n较大时有优化方法博文戳这里...原创 2019-09-22 08:36:18 · 257 阅读 · 0 评论 -
应用举例3.4 等价类划分问题(栈 or 深度优先搜索)
前言根据集合的等价关系(自反,传递,对称),可以利用栈设计一个等价类划分的算法,其中还利用到了类似于邻接表来存储每个成员的等价乙方。题目给n个成员,r组等价关系,输出集合的不同等价类思路并查集如果只是统计不同等价类的数量显然用并查集可以在O(n∗α(k))O(n*α(k))O(n∗α(k))复杂度内完成,但如果是要输出不同等价类,复杂度就会退化到O(n2)O(n^2)O(n2...原创 2019-09-23 11:24:07 · 736 阅读 · 0 评论 -
应用举例4.4 电路布线问题(bfs+记录路径)
问题描述思路实际上就是一个简单的图上的bfs找最短路问题,关于记录前驱路径可以维护一张前驱路径表即可,最后从终点往前找前驱或者后继路径表从起点找后继,当然如果时维护后继表bfs要从终点往起点。关于代码可以参考这篇hdu1484博客。...原创 2019-09-24 12:51:27 · 276 阅读 · 0 评论 -
应用举例11.6 哈夫曼编码(单调队列 or 优先队列)
问题描述每一个单词有一个频率,构造一个压缩算法使其带权路径和最小(叶子节点的频度*深度的累加),并输出每个单词的压缩编码。思路建树贪心构造哈夫曼树的经典压缩算法,以下写几种建树实现的算法:暴力枚举构造因为每次要选取2个当前最小的构成一个小的分支,这两次搜索可以去链表中摘两个最小的块封装成哈夫曼树并放回链表中,迭代n-1次即可,算法复杂度O(n2)O(n^2)O(n2)。具体实现看戳...原创 2019-09-29 10:23:20 · 1122 阅读 · 2 评论 -
算法实验题2.1 向量分类问题(分治 or 广义表)
目录题目思路个人思路书中给的解法笔记实现效果展示总结题目思路个人思路暴力分类O(m2)O(m^2)O(m2)的复杂度进行分类,O(n)O(n)O(n)的复杂度进行比较,总复杂度O(m2n)O(m^2n)O(m2n)广义表结构体:struct node { int sz; //以当前结点的前驱结点为前缀的向量个数 linklist *head; //存相同前缀的...原创 2019-09-22 23:28:54 · 858 阅读 · 1 评论 -
算法实验题2.2 条形图轮廓问题(分治)
题目思路分治,每一个矩形都有一个轮廓图,不妨设它的能代表轮廓线的三个点从左到右存在一张线性表中,当有两个矩形要求其轮廓线一共分为以下几种情况:两个矩形没有交集,靠左的矩形的右边界小于靠右矩形的左边界,即Rl<LrR_l<L_rRl<Lr;两个矩形边相切,靠左的矩形的右边界等于靠右矩形的左边界,即Rl==LrR_l==L_rRl==Lr;两个矩形边相交,...原创 2019-09-23 09:01:49 · 1459 阅读 · 0 评论 -
算法实验题3.1 车皮编序问题(栈+队列+dfs)
问题描述:在一个列车调度站中,1 条轨道连接到1 条侧轨处,形成1 个铁路转轨栈,如下图所示。 其中左边轨道为车皮入口,右边轨道为出口,编号为1,2,…,n 的n 个车皮从入口依次进 入转轨栈,由调度室安排车皮进出栈次序,并对车皮按其出栈次序重新编序a1, a2,., an 。思路:生成全排列,检验是否为出栈序列虽然逻辑简单,但复杂度太高O(n!∗n)O(n!*n)O(n!∗n)...原创 2019-09-23 12:01:50 · 825 阅读 · 0 评论 -
算法实验题3.2 单柱Hanoi塔问题(选择排序 or 搜索+估价剪枝[IDA*])
目录题目描述思路实现题目描述在一个塔座上有一叠大小不等的共n 个圆盘。各圆盘从小到大编号为1,2,……,n。初始时,这些圆盘自下而上散乱地叠在一起。现要求按照以下翻转规则,经若干次翻转,将塔座上的这一叠圆盘排好序,即按自底向上,从大到小的顺序叠置。翻转规则:每次可以将最顶上的若干圆盘翻转,即按其相反的次序叠置。例如,在下面的 3个圆盘叠置状态中,中间状态是在左边状态中第3 个圆...原创 2019-09-24 10:24:50 · 293 阅读 · 0 评论 -
算法实验题3.4 亲兄弟问题(单调栈)
题目描述思路根据题目描述,每个位置的数要去找后面第一个大于等于它值的位置。可以维护一个单调递减栈,当一个值被弹出时就是该位置所在的答案,最后要记得把没出栈的位置标记-1,这些都是找不到答案的。由于每个元素只会出栈进栈各一次,所以复杂度O(n)O(n)O(n)。实现#include <bits/stdc++.h>using namespace std;const in...原创 2019-09-24 10:51:57 · 1109 阅读 · 0 评论 -
算法实验题4.4 逆序表问题(DP or 二分 or 线段树)
题目描述思路这个问题大致就是给你1~n数字对应的逆序数分别存到b[n]中,然后让你还原出原序列动态规划我们虽然不知道原序列长啥样,但我们知道它每个元素长啥样。并且最大那个数无论放到哪逆序数都是为0,于是先把这个数加到结果集中。问题就变成倒2个数根据逆序数考虑排倒结果集的位置,不难发现一个数字k他的逆序数s应满足0<=s<=n−k0<=s<=n-k0<...原创 2019-09-24 22:57:05 · 310 阅读 · 0 评论 -
算法实验题5.3 输油管道问题(中位数定理,分治)
题目描述某石油公司计划建造一条由东向西的主输油管道。该管道要穿过一个有n口油井的油田。从每口油井都要有一条输油管道沿最短路经(或南或北)与主管道相连。如果给定n口油井的位置,即它们的x坐标(东西向)和y坐标(南北向),应如何确定主管道的最优位置,即使各油井到主管道之间的输油管道长度总和最小的位置?如果有两口油井,取两口油井南北方向之间的任意位置如果有三口油井,则取中位数。n口油井即为找...原创 2019-09-25 14:13:29 · 1130 阅读 · 0 评论 -
算法实验题6.5 二叉树先序、中序遍历序列确定后序序列
前言关于二叉树先、中、后遍历序列给一个中序序列以及其他一个就能够推出另一个序列,而如果单单只有先序与后序序列只能得到某两个结点的父子关系而不能确定一个唯一的二叉树。算法主要流程就是搜索,每次通过先序确定根节点,然后根据中序序列确定两个子树的规模,递归下去。复杂度分析在平均情况:T(n)=2∗T(n/2)+nT(n)=2*T(n/2)+nT(n)=2∗T(n/2)+n得:复杂度:O...原创 2019-09-06 00:26:03 · 350 阅读 · 0 评论 -
算法实验题8.1 半数集问题(记忆化搜索)
题目描述问题描述:给定一个自然数n,由n 开始可以依次产生半数集set(n)中的数如下。(1) n∈set(n);(2) 在n 的左边加上一个自然数,但该自然数不能超过最近添加的数的一半;(3) 按此规则进行处理,直到不能再添加自然数为止。例如,set(6)={6,16,26,126,36,136}。半数集set(6)中有6 个元素。注意半数集是多重集。实验任务:对于给定的自然...原创 2019-09-26 18:34:08 · 452 阅读 · 0 评论 -
算法实验题11.2 整数字典问题(线段树 or 平衡树)
问题描述思路平衡树(STL – map)根据题目给的操作分别时原创 2019-09-27 20:35:54 · 133 阅读 · 0 评论 -
习题6.8 递归求LCA到两点路径
**思路:**借助后序遍历的思想求解,链式存储递归求解。注意前缀权值在LCA点处扣的次数,如果归在一条路径上要扣一次,否则扣两次。#include <bits/stdc++.h>using namespace std;struct BiTree { int id; BiTree *lson, *rson; BiTree ():lson(NULL),rs...原创 2019-08-30 18:29:14 · 174 阅读 · 0 评论