
数据结构
一只老风铃
欣于所遇,暂得于己,快然自足。
-
原创 字典树-异或问题
题目描述给定整数m以及n各数字A1,A2,…An,将数列A中所有元素两两异或,共能得到n(n-1)/2个结果,请求出这些结果中大于m的有多少个。输入描述:第一行包含两个整数n,m.第二行给出n个整数A1,A2,…,An。对于30%的数据,1 <= n, m <= 1000对于100%的数据,1 <= n, m, Ai <= 10^5示例1输入3 106 5 10输出2求解思路容易知道如果两个数字异或的结果res大于m, 那么一定是从某一位开始2021-03-02 14:37:445
0
-
原创 最小生成树算法-kruskal与prim
最小生成树算法是图论中的经典贪心算法,主要有kruskal和primkruskal算法其基本思想是:每次加入一条尽可能短的边到目标生成树中首先初始化所有节点为单独的树,可采取并查集father数组表示将所有的边按照权重从小到大排列每次选取一条边,如果边两侧的顶点不再一个集合中,那么合并(加入到最终生成树中)否则,抛弃=》直到挑选了n-1条边(节点数目为n)那么即为最终最小生成树prim算法其基本思想是:每次选择离生成树集合最近的点加入到生成树集合首先初始化其中一个节点加入生成树集.2021-02-28 01:03:3028
0
-
原创 二叉树中最大搜索子树和最大搜索子结构
最大的搜索子树输入描述:第一行输入两个整数 n 和 root,n 表示二叉树的总节点个数,root 表示二叉树的根节点。以下 n 行每行三个整数 fa,lch,rch,表示 fa 的左儿子为 lch,右儿子为 rch。(如果 lch 为 0 则表示 fa 没有左儿子,rch同理)ps:节点的编号就是节点的值。输入3 22 1 31 0 03 0 0输出3基本思路研究root开头的子树是否满足二叉搜索树,满足那么直接返回root的大小否则开始研究root的左右孩子所在子树。2021-01-26 16:31:4633
0
-
原创 二叉树的最近公共祖先
二叉树的最近公共祖先若为传统的tree_node求解问题*基本思路:采取DFS方式,对于当前节点,研究是否为目标节点的一个。然后根据递归子问题的返回,若其中一个子树返回2,那么说明问题已经在子树中解决,否则,计算子树返回的数目+当前节点是否为目标点的数目。最后返回若为多组目标点求解问题基本思路:首先通过DFS建立每个节点=》节点level深度的映射。同时建立每个节点=》父亲节点的映射。(物理存储可能采取map或者数组方式)然后LCA算法过程,首先研究两个点是否在同一Level。如果不2021-01-22 10:50:5125
0
-
原创 前缀树实现最大异或子数组
问题描述数组异或和的定义:把数组中所有的数异或起来得到的值。给定一个整型数组arr,其中可能有正、有负,有零,求其中子数组的最大异或和。输入43 -28 -29 2输出7说明{-28,-29}这个子数组的异或和为7,是所有子数组中最大的思路对于求子数组问题,通常采取动态规划dp[i]=k表示前i项的异或值那么对于其中的【i=>j】其异或值为dp[j]与dp[i-1]的“异或值做除法"本题思路是维护一个前缀数组,即字典树形式计算XOR[]表示前i项的异或值,那么对2021-01-15 11:19:3820
0
-
原创 Leetcode:单调栈_可见山峰问题
题目描述一个不含有负数的数组可以代表一圈环形山,每个位置的值代表山的高度。比如,{3,1,2,4,5},{4,5,3,1,2}或{1,2,4,5,3}都代表同样结构的环形山。3->1->2->4->5->3 方向叫作 next 方向(逆时针),3->5->4->2->1->3 方向叫作 last 方向(顺时针)。山峰 A 和 山峰 B 能够相互看见的条件为:如果 A 和 B 是同一座山,认为不能相互看见。如果 A 和 B 是不同的山,并且2020-12-12 04:25:2578
0
-
原创 单调栈结构
问题引出单调栈是这样一类结构,栈中的元素有序,例如一个单调递增栈,如果新来的元素比栈顶更大,那么入栈;如果新来的元素比栈顶更小,那么弹出若干栈顶元素,直到新来的元素能够入栈单调栈经典问题:条形图的最大矩形面积该问题,维护一个单调递增栈,如果新来的元素比栈顶小,那么开始一个count计数弹出。不断计算矩形面积:count*stack.top() 即使每次的矩形是top高度×当前矩形的长(count计数)。同时弹出count个元素,重新压入count+1个新元素(新元素使得前面部分减少:短板效2020-12-10 17:33:3254
0
-
原创 双堆实现任意删除:天际线扫描
堆的删除堆其结构为完全二叉树,物理存储采取数组,一个点I 其孩子节点为 2i+1 2i+2 堆的操作包含top() pop() push()并且这些操作都是基于堆的顶部进行,其通常调用down下沉操作和up上浮操作。堆不支持任意节点的删除(意味着节点之间顺序打乱)。通常可以基于双堆实现逻辑删除。class my_heap{ private: priority_queue<int> q1; //最大堆 priority_queue<int>2020-11-21 12:08:3537
0
-
原创 huffman树:最小拆分代价即最小带权路径和
huffman树给定N个权值作为N个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。huffman树使得原先不同权重的叶子节点经过整合按照不同的层次进行分布,其具有的特点是:值越大的叶子节点,距离根节点越近。值越小的叶子节点,距离根节点越远。根据huffman树最优带权路径的特性,产生了huffman编码:从huffman树根节点开始,沿左边编码0 沿右边编码1 从根节点到叶子2020-11-19 02:37:1781
0
-
原创 Leetcode 双堆实现排序
双堆思路双堆,一个最大堆,一个最小堆通常用于实现某种排序查找策略,可以维护在O(NlogN)的时间复杂度。典型的例子是实现输入流的中位数快速查找,其可以在O(1)的时间内返回中位数。基本思路是,维护两个大小相等(或相差不超过1的堆每次新来的数字判断其与最大堆的堆顶(较小那一部分集合的最大值)大小,来决定加入到哪一部分,并合适的移动,使得两边维护者数量相等的部分。题目描述给定两个整数W和K,W代表你拥有的初始资金,K代表你最多可以做K个项目。再给定两个长度为N的正数数组costs[]和profi2020-11-19 01:15:3426
0
-
原创 Linux进程执行环境
进程环境进程的环境,主要是描述是对程序执行时,main函数如何被调用;命令行参数以及环境变量如何传递给程序;进程的存储空间布局形式;以及进程终止方式;进程的资源限制等问题。一个典型的C程序总是从main开始执行 int main(argc,char* argv[]) 内核执行C程序时,其通过父进程采取exec函数,在调用main之前先调用一个启动例程。启动例程将命令行参数和环境变量从内核中获取,传递给进程。一个典型的C程序启动与终止:可以看到,总是从一个C启动例程开始,由它启动main函数,而2020-11-14 02:49:3443
0
-
原创 Leetcode 服务器分发
共有n台服务器,每台服务器可以和若干个子服务器传输数据,n台服务器组成一个树状结构。现在要将一份数据从root节点开始分发给所有服务器。一次数据传输需要一个小时时间,一个节点可以同时对k个儿子节点进行并行传输,不同节点可以并行分发。问,全部分发完成,最短需要多少小时?【示例】:当共有5台服务器,其树状结构为 0 /\ 12 / \3 4假设每一台服务器同时可以对1个儿子节点(k=1)并行传输,最优的数据传...2020-10-19 15:05:2140
0
-
原创 Leetcode 关于链表排序与元素删除
链表问题通常有两大类思路:修改节点指针:使得它们以符合要求的顺序勾连,例如链表翻转修改节点内容:不修改节点指向,而是采取交换或修改其中节点的值【问题①:删除链表中node* p指向的节点】思路:由于没有前置节点,故无法物理取消前置节点到该节点的勾连,采用下一个节点的值覆盖当前节点的值(实际删除下一个节点)void del(node* p){ p->val=p->next->val; p->next=p->next->next;}注意只2020-10-17 01:38:2424
0
-
原创 Leetcode 关于出栈序列:状态转移DFS+全排列+模拟
已知某一个字母序列,把序列中的字母按出现顺序压入一个栈,在入栈的任意过程中,允许栈中的字母出栈,求所有可能的出栈顺序。例如:入栈顺序:abc其所有可能出栈顺序。abcacbbacbcacba【思路一】状态转移+DFS模拟出所有操作:容易知道一个状态包含以下三部分:常见的状态转移过程:q1为空 stack为空 =》那么所有元素都已经出栈,输出出栈序列,为终止状态 q1为空 stack不为空 =》那么只能出...2020-10-17 01:25:0327
1
-
原创 Leetcode 单双字典树
题目描述有n个只包含小写字母的串s1,s2,..sn,每次给你一个只包含小写字母的串t。如果串S存在前缀S',它的奇数位的字符与t的奇数位字符完全相同,称S为t的单匹配串,如果串S的偶数位字符与t的偶数位的字符全都相同,称S为t的双匹配串。现在给你m个字符串,对于每个字符串t,求s1,s2,...sn中有多少个串是t的单匹配串但不是t的双匹配串。示例1输入复制3,["abc", "bbc", "cbd"],3,["abc","cad","bac"]输出复制2020-10-07 00:09:1732
0
-
原创 二叉树右视图
题目描述请根据二叉树的前序遍历,中序遍历恢复二叉树,并打印出二叉树的右视图示例1输入复制[1,2,4,5,3],[4,2,5,1,3]输出复制[1,3,5]基本思路:先构建二叉树然后层次遍历,记录下每一层的最后一个节点(或者层次遍历从右往左)易错点:层次遍历每一层之前先记录下队列大小。struct treenode{ int val; treenode* left; treenode* right; ..2020-10-03 22:58:3231
0
-
原创 Leetcode 堆排序
堆是完全二叉树,即对于一个节点k 其孩子节点为2k+1 2k+2 (存在孩子节点情况下) 满足任意一个节点值大于(或小于)其孩子节点值,在建立和调整堆的过程包含两大操作:shift_up:向上调整,通常用于末尾添加一个新节点后,向上方向移动若干个位置,即不断判断其父亲节点是否更小,若是:交换 shift_down:向下调整,当根节点删除后,需要在根节点补充一个(通常是末尾),该元素需要下沉到合适位置,基本策略是:若当前节点比左右孩子节点都大,无需调整。 否则,找到孩子节点的最大值,与当前...2020-10-02 10:01:2145
0
-
原创 Trie字典树
字典树,顾名思义,存放大量单词的字典,将每个单词按照char分隔开,依次从根节点开始下降到某一节点,而路径则记录着单词的信息。其中每一个节点主要包含的信息有:int next[26] 其中next[i]=k表示引向字符'a'+i的边指向节点k(这里的k指的是下一个节点所在下标(若采取离散存储则是地址)) 若k=0 表示没有next边(因为0存放root节点) int sum;表示以该node节点为末尾的单词的数目(删除则sum-- 增加则sum++) int pre_sum; 表示...2020-09-20 00:38:5819
0
-
原创 bitmap 位存储实现海量数据的标记
针对海量的数据,一般的内存无法存储,提供一种位存储的标记方法?如给定10亿个数字,询问其中任意一个数字是否出现,采取传统的存储方式,以32位机器为例一个int占用32位,也就是4字节而bitmap的思想是,无符号int类型的范围是确定的 即0~2的32次方-1那么将一个int拆分开来看,其包含32个bit 若其中一个Bit为1那么标记原先的数字存在 那么对于一组int第一个int: 表示0~31这32个数字第二个int: 表示32~63这32个数字......对于任意...2020-09-10 13:53:44138
0
-
原创 unordered_map的实现-hashmap
C++STL中map包含两大类map:采取红黑树方式,map中的元素有序,读写都是O(LogN)的时间复杂度 unordered_map:元素无序,采取hashmap的实现方式,即连续存放的桶,数组+链表方式,一般的认为读写都是O(1)复杂度unordered_map是典型的采取空间换时间的方式达到一个良好的性能,初始化一定大小的vector(连续存储的数组)vector中index位置下标元素为一个bucket(桶) 针对一个(key,value)根据hash函数(常见的如 取模%)定.2020-09-10 11:22:4366
0
-
原创 Leetcode 树的直径(树中最远的两个点)
题目描述给定一棵树,求出这棵树的直径,即两个节点距离的最大值。示例1输入复制6,[[0,1],[1,5],[1,2],[2,3],[2,4]],[3,4,2,1,5]输出复制11思路:从任意一个点出发找到最远的点P 从P点出发找到最远的点Q P Q之间的距离即为树中最远两个点距离证明:实现:采取基本的dfs 实现搜索最远的点,找到他们之后采取dfs 返回两者的距离int point_p; ...2020-09-06 12:45:32339
0
-
原创 Leetcode 栈输出之排序
题目描述给你一个1->n的排列和一个栈,入栈顺序给定你要在不打乱入栈顺序的情况下,对数组进行从大到小排序当无法完全排序时,请输出字典序最大的出栈序列示例1输入复制[2,1,5,3,4]输出复制[5,4,3,1,2]说明2入栈;1入栈;5入栈;5出栈;3入栈;4入栈;4出栈;3出栈;1出栈;2出栈基本思路:容易知道,第一个输出的数字一定是最大的那个数字,其操作为一直入栈到最大的数字,然后弹栈输出该最大的数字那么第二输出...2020-09-06 10:20:12144
0
-
原创 Leetcode 搜索二叉树中错误节点
题目描述一棵二叉树原本是搜索二叉树,但是其中有两个节点调换了位置,使得这棵二叉树不再是搜索二叉树,请按升序输出这两个错误节点的值。(每个节点的值各不相同)思路:搜索二叉树最重要性质为中序遍历为升序那么交换的可能是前后两个节点交换,那么中序遍历存在一组逆序对 中间隔开若开个节点交换,那么中序遍历存在两组逆序对那么只要记录下第一组逆序对的第一个元素,以及最后一组逆序对的第二个元素,即为原先交换的两个数关键实现 对于一组逆序对(first,second) ...2020-09-06 06:13:19127
0
-
原创 Leetcode 搜索二叉树与完全二叉树的判断
搜索二叉树:中序遍历为递增序列,如果不是,返回false完全二叉树:层次遍历中,不出现以下情况一个节点,其左子树为空,右子树不为空 遍历到一个叶子节点或(该节点左子树不为空,右子树为空),其以后的所有节点必须全部为叶子节点BST判定 采取stack非递归实现 //判断是否为搜索二叉树 中序遍历即可,若非递增那么不是 bool BSTJudge(TreeNode* root) { stack<TreeNode*> ...2020-09-02 11:13:40122
0
-
原创 Leetcode LFU_Cache缓存结构设计
之前LRU最近最久未使用缓存结构设计采取存储方式为map<key,List<pair<int,int>>::iterator> 存放key到(key,value)映射 可直接get到 List<pair<key,value>> 存放(key,value)链表 维护大小为k 末尾为最久未使用题目描述一个缓存结构需要实现...2020-08-28 14:23:03140
0
-
原创 基本数据结构 最小堆
最小堆,是完全二叉树,其基本定义是任何一个节点小于其左右子树的节点常见操作:加入一个值,取最小值,删除最小值加入一个值,直接加入到末尾a[size++] 然后该元素上浮到合适位置最大值即根节点 a[0]删除最小值,让末尾元素填充到a[0] 然后该元素下沉到合适位置下沉过程中,选取左右子节点的最小值,上浮(任满足节点大于左右子树)易错点,树中没有节点,以及下沉过程中,是否存在左右子树的判断(即基本的数组区间判断)class heap{public: int ...2020-08-02 13:11:58106
0
-
原创 Leetcode Min_stack
实现能够取最小值得stack原理:其中主栈和stack类似存取,另一个辅助栈在新入值更小时 插入当主栈弹出元素时,判断是否是辅助栈栈顶 若是 那么辅助栈同步弹出class min_stack{private: stack<int> S; stack<int> S_min;public: void push(int a) { if (this->S_min.empty() || a <= S_min.top()) //当且仅当新入..2020-07-13 19:27:1630
0
-
原创 动态规划 二叉搜索树的种类
【问题描述】给定从1到n的n个编号的节点,问这些节点可以构成多少种不同的二叉搜索树?当n=1时,只有1种当n=2时候,有2种以1为根节点 以2为根节点当n=3时,有3大类,共5种以1为根节点 以2为根节点 以3为根节点【求解思路】对于1到n个节点,其最终的二叉搜索树的种类可以分为n大类;即以1为根节点以2为根节点以3为根节点........2020-01-06 15:36:25157
0
-
原创 最小堆 数据流中的中位数
实现Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。思路:采用一个最大堆maxHeap,一个最小堆minHeap最大堆的数据都小于最小堆的数据,同时维护2个堆的数据数目count相等,或最小堆的数目比最大堆大1这样中位数一定是2个堆的堆顶元素平均值,或者一定位于最小堆的堆顶细节:如果当前2个堆数目相等,那么向最小堆插入数据之前,需...2019-03-18 17:41:2268
0
-
原创 二叉树 二叉搜索树与双向链表
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。思路:二叉搜索树,左节点<根节点<右节点中序遍历即为 从小到大的递增序列 struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; ...2019-02-17 12:46:19155
0
-
原创 图 无向图保证连通性
无向图有8个顶点,保证无论何种情况下图都是联通的,则最少的边的数目?要保证无向图G在任何情况下都是连通的,即任意变动图G中的边,G始终保持连通。首先需要图G的任意7个结点构成完全连通子图G1,需n(n-1)/2=7×(7-1)/2=21条边,然后再添加一条边将第8个结点与G1连接起来,共需22条边。证明:若其中七个点小于21条边,那么还可以向这7个点加入一条边(还没有达到完...2019-09-16 19:46:191117
0
-
原创 Hash 哈希冲突与解决方法
Hash冲突,当2个不同的元素的Key通过Hash()算法得到相同的目标地址时,发生Hash冲突主流的解决方法有:——开放地址法这种方法也称再散列法,其基本思想是:当关键字key的哈希地址p=H(key)出现冲突时,以p为基础,产生另一个哈希地址p1,如果p1仍然冲突,再以p为基础,产生另一个哈希地址p2,…,直到找出一个不冲突的哈希地址pi ,将相应元素存入其中。这种方法有一个通用的...2019-03-14 08:55:49161
0
-
原创 链表 寻找2个链表的第一个公共节点
输入两个链表,找出它们的第一个公共结点。思路:由于从某个节点开始2个链表相交,那么之后的节点完全一样先求出2个连表长度 先使得长的链表 先走差值的长度然后2个指针并排前进,并判断是否相等,若相等即为第一个公共节点(需要注意 NULL的情况)class Solution {public: ListNode* FindFirstCommonNode( ListNod...2019-02-26 18:46:24172
0
-
原创 二叉树 寻找二叉搜索树第K大的节点
给定一颗二叉搜索树,返回该二叉搜索树第K大的节点思路:由于二叉搜索树的中序遍历序列是从小到大的序列,模拟这一过程每访问一个节点,count++直到第K个注意点:由于递归的进入与返回过程,递归调用栈频繁进出,计数器可设置成全局的变量 递归的返回条件是NULL 注意特殊情况class Solution {public: int count=0;//计数器 注意设置成全局,...2019-03-05 10:29:104737
0
-
原创 数据结构 栈的入栈、出栈序列
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。思路:每次将入栈序列一个元素入栈,判断当前栈顶和出栈序列判断处(初始化为第一个元素)是否匹配若相等,则弹出该元素、同时...2019-02-23 17:12:071846
0
-
原创 算法 包含min函数的栈
定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。思路:——双栈模拟,stack1为实际数据栈,satck2则存放各阶段的最小值(倒三角)——核心问题 解决掉多个相同最小值的情况——(关键步骤stack出栈时,min值的问题 判断stack1栈顶和stack2栈顶是否相等)class Solution {public:...2019-02-22 23:33:5552
0
-
原创 二叉树 二叉树中和为某一值的路径
输入一颗二叉树的跟节点和一个整数,打印出二叉树路径中结点值的和为给定整数的所有路径。路径定义:从树的根结点开始往下一直到叶结点经过的所有结点称为一条路径。(注意: 在返回值的list中,数组长度大的数组靠前) 基本思路:从根节点处向下遍历,保存之前所有节点的和当到达叶子节点时,判断是否符合条件struct TreeNode { int val; str...2019-02-18 10:40:3264
0
-
原创 二叉树 重构二叉树
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。 基本思路: 前序遍历 根节点-》左子树-》右子树 所以前序序列中第一个元素总是为根节点 中序遍历 左子树-》根节点-》右子树 所以中序序列中 根节点在序列内部 可以进一步划分出 左右子树...2019-02-17 12:07:1462
0
-
原创 数据结构 栈和队列的相互模拟
利用2个栈模拟队列、利用2个队列模拟栈 双栈模拟队列用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。初始化2个栈stack1 stack2每次入队列总是压入stack1栈顶而每次出队列总是从stack2栈顶弹出若stack2为空则将stack1元素全部弹出压入stack2(始终确保先进先出) class Queue{...2019-02-17 11:58:57164
0
-
原创 链表 寻找链表倒数第k个节点
输入一个链表,输出该链表中倒数第k个结点。没有返回NULL基本思路:先判断链表长度是否大于等于K 初始化2个指针P1 P2为Head 其中P1先向前走K步然后2个指针不断向下走直到P1到达尾节点 那么P2即为倒数第K个节点struct ListNode { int val; struct ListNode *next; ListNode(int ...2019-02-17 11:42:25106
0