
数据结构与算法
文章平均质量分 70
鱼思故渊
这个作者很懒,什么都没留下…
展开
-
最大连续子序列乘积
问题描述给定一个整数序列(可能有正数,0和负数),求它的一个最大连续子序列乘积。比如给定数组a={3, -4, -5, 6, -2},则最大连续子序列乘积为360,即3*(-4)*(-5)*6=360。分析求最大连续子序列乘积与最大连续子序列和问题有所不同,因为其中有正有负还有可能有0。假设数组为a[],直接利用动归来求解,考虑到可能存在负数的情况,我们用Max[i]来原创 2015-01-08 22:21:08 · 983 阅读 · 0 评论 -
为什么只给出前序和后序,不能唯一确定一个二叉树
我们在学习二叉树的遍历时,都会不可避免的学到二叉树的三种遍历方式,分别是遵循(根-左-右)的前序遍历、遵循(左-根-右)的中序遍历以及遵循(左-右-根)的后序遍历。并且每一个二叉树都可以用这三种遍历方式并且分别转换为字符串序列,以便在计算机上面保存。但是我们在进行逆向操作的时候却会遇到困难:我们并不能从某一种遍历方式推断出唯一的二叉树,也就是说,这是个单向编码的过程。而当我们有一个二叉树的两种遍历转载 2015-01-13 22:55:52 · 14369 阅读 · 5 评论 -
位操作基础篇
转载:http://blog.youkuaiyun.com/morewindows/article/details/7354571在计算机中所有数据都是以二进制的形式储存的。位运算其实就是直接对在内存中的二进制数据进行操作,因此处理数据的速度非常快。在实际编程中,如果能巧妙运用位操作,完全可以达到四两拨千斤的效果,正因为位操作的这些优点,所以位操作在各大IT公司的笔试面试中一直是个热点问题。因此本转载 2015-01-14 14:40:20 · 768 阅读 · 0 评论 -
二路归并 && 插入归并 && 原地归并
插入归并归并排序的时间复杂度为O(nlgn),空间复杂度为O(n);但是一般来讲,基于从单个记录开始两两归并的排序并不是特别提倡,一种比较常用的改进就是结合插入排序,即先利用插入排序获得较长的有序子序列,然后再两两归并(改进后的归并亦是稳定的,因为插入排序是稳定的)。之所以这样改进是有原因的:尽管插入排序的最坏情况是O(n^2),看起来大于归并的最坏情况O(nlgn),但通常情况下,由于插原创 2015-01-17 17:38:32 · 1724 阅读 · 0 评论 -
二叉树中任意两节点的最低共同父节点
通过两个和二叉树相关的算法题来看看和递归在二叉树中的应用输入二叉树中的两个结点,输出这两个结点在数中最低的共同父结点。 思路: 如果这两个节点不在同一个子树下面,那么这棵树的根节点就是他们的共同最低父节点。如果两个都在右子树,那么以右子树的最上面的那个节点作为根节点,重新进行判断,递归调用。同理两个都在左子树,则方法同上。 也就是说,最终的结果分别只有三种情况,一个节点在原创 2015-01-05 14:34:49 · 5180 阅读 · 1 评论 -
相邻元素差的绝对值都是1,在这样的数组中找目标元素
有这样一个数组A,大小为n,相邻元素差的绝对值都是1。如:A={4,5,6,5,6,7,8,9,10,9}。现在,给定A和目标整数t,请找到t在A中的位置。除了依次遍历,还有更好的方法么?这道题目的解法非常有趣。数组第一个数为array[0],要找的数为y,设t = abs(y - array[0])。由于每个相邻的数字之差的绝对值为1。故第t个位置之前的数肯定都比y小。因此直接定位到原创 2015-01-18 17:00:36 · 2974 阅读 · 0 评论 -
最长单调递减子序列
问题描述:求一个数组的最长递减子序列 比如{9,4,3,2,5,4,3,2}的最长递减子序列为{9,5,4,3,2}。思路:这是一个标准的动态规划的问题,在不理解算法的时候,最感觉可以使用递归的思想,其实也是正确的,在最后给出一个递归的方法,在知道是动态规划问题以后,就需要进行分析,我们需要一个辅助数组记录信息,假如源数组为src,辅助数组为table,table[i]数组中记录着到src原创 2014-09-17 09:25:27 · 2702 阅读 · 3 评论 -
两个整数 n 和 m,从数列1,2,3.......n 中 随意取几个数, 使其和为 m
/*输入两个数m和n ,从数列1,2,3,4,.....n这些数中挑选几个使得和为m,找出所有的这样的组合*/void FindSum(int m,intn,vector& vec){ if(m < 0 || n < 0) return ; if(m == 0) { vector::iterator itr = ve原创 2015-01-04 08:57:23 · 1398 阅读 · 0 评论 -
二叉搜索树的创建 && 查找 & 插入 & 删除
二叉搜索树的删除:在删除之前需要从树中查找到这个节点,然后再针对情况来判断如何删除。分为三种情况,首先是此节点没有孩子节点,此节点有一个孩子节点,此节点有两个孩子节点void Delete(BinTree*& root,int value){ BinTree* delnode= NULL; if(root == NULL) return ; BinTree* temp原创 2015-01-19 10:47:55 · 1106 阅读 · 0 评论 -
一串首尾相连的珠子(m个),有N种颜色(N<=10),使得最短的字符串包含全部颜色
思路:先从index=0处搜索,每检查一颗珠子,响应的颜色数量+1,如果是新的颜色则总颜色数+1. 当颜色总数为n时,找到第一个满足条件的连续序列。 1>从该序列起始处搜索,若搜索处的颜色数量不为1,则表明该串还有别的珠子有该颜色,继续往前搜索并更新该序列,起始索引位置+1.原创 2015-01-14 19:27:33 · 2731 阅读 · 1 评论 -
Trie树的详解及应用
Trie树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:最大限度地减少无谓的字符串比较,查询效率比哈希表高。Trie的核心思想是空间换时间。利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的。 Trie 的强大之处就在于它的时间复杂度。它的插入和查询时间复杂度原创 2015-01-14 20:21:48 · 1675 阅读 · 0 评论 -
红黑树插入删除节点过程分析 && C代码实现
红黑树的插入和删除规则:红黑树的五个性质1、 每个节点要么是红的,要么是黑的2、 根节点时黑色的3、 每个叶节点(叶节点既指树尾端NIL指针或NULL节点)是黑色的4、 如果一个节点时红的,那么它的两个儿子都是黑色的5、 对每个节点,其到叶节点树尾端NIL指针的每一条路径都包含相同数目的黑节点这里所说的“叶节点”或者“NULL节点”,它不包原创 2015-01-28 13:42:23 · 1590 阅读 · 0 评论 -
等概率无重复的从n个数中选取m个数
问题描述:程序的输入包含两个整数m和n,其中m学习过概率统计的同学应该都知道每一个数字被抽取的概率都应该为m/n. 那么我们怎么构造出这样的概率呢?在《编程珠玑》上面是这样解析的: 依次考虑整数0,1,2,.....,n-1,并通过一个适当的随机测试对每个整数进行选择。通过按序访问整数,我们可以保证输出结果是有序的。 假如我们考虑m = 2,n = 5的情况,那么选择的每一个数字的概率都原创 2015-01-11 08:57:27 · 21037 阅读 · 0 评论 -
利用随机函数生成随机数
给定一个rand(),可以产生从0到RAND_MAX的随机数,其中RAND_MAX很大(常见值:16位int能表示的最大整数32767),写出利用rand()生成[a,b]中任意整数的函数,其中a>=0, b分析:这是在编程工作最常见的随机函数的应用,在这里做一个起点再合适不过。把随机数区间的起点从0变为a,同时把一共RAND_MAX+1个数的区间缩小至只含有b-a+1个数的区间,写为 a原创 2015-01-11 09:01:53 · 4005 阅读 · 0 评论 -
将二叉树转化为双向链表
递归解法:(1)如果二叉树查找树为空,不需要转换,对应双向链表的第一个节点是NULL,最后一个节点是NULL(2)如果二叉查找树不为空:如果左子树为空,对应双向有序链表的第一个节点是根节点,左边不需要其他操作;如果左子树不为空,转换左子树,二叉查找树对应双向有序链表的第一个节点就是左子树转换后双向有序链表的第一个节点,同时将根节点和左子树转换后的双向有序链 表的最后一个节点连接;原创 2015-01-29 08:50:43 · 2098 阅读 · 0 评论 -
小白鼠试毒药,最少需要多少即可试出结果
有 1000 桶酒,其中 1 桶有毒。而一旦吃了,毒性会在 1 周后发作。现在我们用小老鼠做实验,要在 1 周内找出那桶毒酒,问最少需要多少老鼠。一只老鼠喝酒后又两种状态:死(0)和活(1).所以10只老鼠就能表示2的10次方个状态(即1024个)。2^0表示2的零次方。2^8表示2的8次方。设有10只老鼠编号分别为2^0,2^1, 2^2, 2^3, 2^4, 2^5,原创 2015-01-13 14:27:37 · 4115 阅读 · 0 评论 -
一个整数数组,长度为n,将其分为m 份,使各份的和相等,求m 的最大值
划分为m块时,需要具备的条件:m的取值为1~n每一部分之和为 sum/m; (sum为数组元素之和)sum % m == 0,否则不可能平分递归思想:假设分为m块,每一块之和即为subSum = sum / m。subSum即为每一块元素之和。如果array[i]在某一个块中,则需要在数组的其中元素中找出和值为(subSum - array[i])的组合。利用boo转载 2015-01-14 11:43:10 · 3563 阅读 · 0 评论 -
比较排序算法
比较排序算法分类比较排序(Comparison Sort)通过对数组中的元素进行比较来实现排序。比较排序算法(Comparison Sorts)CategoryNameBestAverageWorstMemoryStability 插入排序 (Insertion Sorts)转载 2015-01-13 17:33:28 · 1073 阅读 · 0 评论 -
链表的归并排序
因为链表是节点式存储,不能做到随机存储,但是对于两个有序链表之间的合并不需要额外的空间,在O(1)空间复杂度O(n)时间复杂度内即可完成。所以对于链表排序,使用归并排序比较划算。typedef struct Node List;struct Node{ int value; List* next; }; //链表节点结构体首先合并两个原创 2015-01-14 18:05:09 · 1193 阅读 · 0 评论 -
二叉树的序列化与反序列化
一个二叉树被序列化为数组,如何反序列化,也就是如何从序列化好的一个数组恢复成二叉树?在上一篇文章中讲述了如何将一个有序数组创建成一个二叉搜索树,那么如果将将一个儿茶搜索树序列化为一个有序数组,然后按照上面的方法在反序列化即可。对二叉搜索树进行中序遍历即可得到一个有序的数组,那么上篇文章已经完成了对二叉搜索树的序列化和反序列化。同时如果想将二叉搜索树的序列化和反序列化的结果通过文件读取,也是同样原创 2015-01-04 19:15:28 · 2652 阅读 · 0 评论 -
如何将一个有序数组快速插入到一个二叉树中
输入一个有序的数组,如何实现将这个有序整数数组放到二叉树中?分析:对于二叉树,可以将这个有序数组插入到二叉搜索树中,毕竟二叉搜索树还是有很多特定的。那么对于创建二叉搜索树来说,就是简单的递归了。关于树的算法设计一定要联想到递归,因为树本身就是递归的函数。那么可以对于这个有序数组分析,将这个数组的中位数作为根节点,然后对于数组的前半部分创建一个树作为根节点的左子树,后半部分创建一个二叉搜索树原创 2015-01-04 16:21:20 · 3319 阅读 · 0 评论 -
二叉查找树的镜像
题目:输入一颗二元查找树,将该树转换为它的镜像,即在转换后的二元查找树中,左子树的结点都大于右子树的结点。用递归和循环两种方法完成树的镜像转换。例如输入:8/ \6 10/\ /\5 7 9 11输出:8/ \10 6/\ /\11 9 7 5思路:这也是一个递归的题目,对于当前节点,如果不是NULL节点或者叶子节点,那么只需要交换左右子节点原创 2015-04-29 08:53:14 · 1316 阅读 · 0 评论 -
求前K个数
描述一个算法,在十亿个(n)数中找出前一百万(k)大的数字。假设内存里可以放下十亿个数。思路:1、直接排序,然后输出前一百万个数,时间复杂度为O(n*logn)。2、维护一个大小为一百万的大顶推,然后遍历完十亿个数,输出大顶推的数即可,时间复杂度为O(n*logk)。该思路适合大数据,尤其是内存放不下所有数据的时候。3、利用快排的思想进行划分,一次划分后设主元的位置为index,如原创 2013-10-19 22:48:21 · 1602 阅读 · 0 评论 -
矩阵行走路径问题
1、一个m*n的矩阵a[][],机器人从左上角走到右下角,只能朝右或朝下走,输出所有路径。2、如果矩阵有的格子可以走,有的格子不可以走,输出所有路径。(a[i][j]==1表示可以走,a[i][j]==0表示不可以走)思路:典型的递归算法。问题1直接用深搜的思想。问题2在问题1的基础上加个判断条件即可。[cpp]view plaincopy#includ原创 2013-10-19 22:18:36 · 4005 阅读 · 0 评论 -
数对之差的最大值 && 子数组的最大和
问题1: 在数组中,数字减去他的右边的数字得到一个数对之差,求所有数对之差的最大值。 例如数组{2.4.1.16.7.5.11.9}中,数对之差的最大值是11,是16减去5的结果。 问题2:给定一个含有n 个元素的数列,元素有正有负,找出和最小的一组相邻的书,既给定a[n],是的a[i]+a[i+1]+...+a[j]的和最小。先看第一道题目:如果从头遍历,遍历到某一个位置,从这个位置原创 2015-01-08 15:39:11 · 1730 阅读 · 0 评论 -
二分查找的实现
在一个有序的数组中,查找一个数,可以使用二分查找,但是这个算法也是有很多地方需要注意的。正确的写法如下所示。//首先要把握下面几个要点: //high=n-1 => while(low high=middle-1; //high=n => while(low high=middle; //middle的计算不能写在while循环外,否则无法得到更新。i原创 2015-08-28 15:29:20 · 1656 阅读 · 0 评论 -
二叉树的非递归遍历(前序、中序、后序)
先序遍历void PreOrder_Nonrecursive1(BiTree T) //先序遍历的非递归 { if(!T) return ; stack s; BiTree curr = T; while(curr != NULL || !s.empty()) { while(原创 2015-07-17 08:01:17 · 1356 阅读 · 0 评论 -
二叉树两个结点的最低共同父结点
入二叉树中的两个结点,输出这两个结点在数中最低的共同父结点。分析:求数中两个结点的最低共同结点是面试中经常出现的一个问题。这个问题至少有两个变种。第一变种是二叉树是一种特殊的二叉树:查找二叉树。也就是树是排序过的,位于左子树上的结点都比父结点小, 而位于右子树的结点都比父结点大。 我们只需要从根结点开始和两个结点进行比较。 如果当前结点的值比两个结点都大, 则最低的共同父结点一原创 2015-04-29 11:40:30 · 2357 阅读 · 0 评论 -
输出 1 到最大的 N 位数
题目:输入数字 n,按顺序输出从 1 最大的 n 位 10 进制数。比如输入 3,则输出 1、2、3 一直到最大的 3位数即 999。思路:这是一个大数问题,必须使用一个字符串来表示数字,因为担心数字太大void Add(string& cur){ int carry =1; int temp; int i; for(i=0;i<cur.length();i++) {原创 2015-04-29 10:54:26 · 1063 阅读 · 0 评论 -
使用递归反转一个栈
反转递归栈的内容使用递归,一定要明白递归结束的条件,假如栈中只有一个元素或者没有元素,那么这个栈就不用递归。那么我们将栈顶元素取出来,将余下的元素进行反转,那么将取出的元素放到栈的底部即可。对于将一个元素放到底部,又是一个递归的调用,如果栈为空,那么直接将元素存放到栈的底部即可,如果栈中有元素,那么取出栈内的元素,将原来的元素再次调用函数存放到栈底,然后将取出的元素压入栈即可。感觉这个原创 2015-08-21 11:26:50 · 3777 阅读 · 1 评论 -
求一个序列的所有排列
在C++ STL标准模板库中已经有线程的思想,这样就是介绍STL中的思想。其实也可以使用递归的方法解决,后续问题,STL中的方法也解决了有重复字符的问题。思路: 借助了字典序的方法,首先将序列按照升序进行排序(当然也可以使用降序排列,都是一样的道理),将这个序列作为一个字典序的输入序列,从这个字典序如何变换出下一个字典序列呢?对这个序列从后往前进行搜索,找到一对相邻的升原创 2014-10-11 15:33:30 · 1322 阅读 · 0 评论 -
n个骰子各点数和出现的概率--动态规划
题目:把n个骰子扔在地上,所有骰子朝上一面的点数之和为S。输入n,打印出S的所有可能的值出现的概率。声明思想非原创!只因动态规划思想的使用很好,记下!分析:动态规划就是分阶段考虑问题,给出变量,找出相邻阶段间的关系。具体定义给忘了。1.现在变量有:骰子个数,点数和。当有k个骰子,点数和为n时,出现次数记为f(k,n)。那与k-1个骰子阶段之间的关系是怎样的?2.当我有k-1个骰子时原创 2014-11-12 19:01:52 · 5117 阅读 · 0 评论 -
约瑟夫环问题
题目:n 个数字(0,1,…,n-1)形成一个圆圈,从数字 0 开始,每次从这个圆圈中删除第 m 个数字(第一个为当前数字本身,第二个为当前数字的下一个数字) 。 当一个数字删除后,从被删除数字的下一个继续删除第 m 个数字。求出在这个圆圈中剩下的最后一个数字思路:这就是约瑟夫环问题,使用STL中的list来解决,是最基础的解决办法int Joseph(list& ring,int原创 2015-04-29 08:44:47 · 1258 阅读 · 1 评论 -
和为 n 连续正数序列
题目:输入一个正数 n,输出所有和为 n 连续正数序列。例如输入 15,由于 1+2+3+4+5=4+5+6=7+8=15,所以输出 3 个连续序列 1-5、4-6 和 7-8。思路:我们再找连续的序列,那么我们从最小的一直往前加,如果和结果相等,那么这是一个符合条件的序列,然后再连续的往后加,如果和比结果小,那么一直往后加,如果比结果大,那么需要取出前面小的值,因为后面大的值是刚添加上的原创 2015-04-29 09:41:46 · 1061 阅读 · 0 评论 -
判断一个序列是否是一个二叉查找树的后序遍历结果
题目:输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果。如果是返回 true,否则返回 false 。例如输入 5、7、6、9、11 、10、8,由于这一整数序列是如下树的后序遍历结果:8/ \6 10/ \ / \5 7 9 11因此返回 true。如果输入 7、4、6、5,没有哪棵树的后序遍历的结果是这个序列,因此返回 false 。思路:原创 2015-04-28 23:08:21 · 1058 阅读 · 0 评论 -
二叉查找树转换成排序的双向链表
题目:输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。要求不能创建任何新的结点,只调整指针的指向。比如将二元查找树10/ \6 14/ \ / \4 8 12 16转换成双向链表4=6=8=10=12=14=16。思路:对于树的很多题目,都可以使用递归的方法来处理。这道题目也不例外。我们从最基本的思路来考虑这个题目。把一个二叉树编程双向链表,原创 2015-04-28 21:57:51 · 1002 阅读 · 0 评论 -
判断树为另一树的子结构
输入两棵二叉树 A 和 B,判断树 B 是不是 A 的子结构。例如,下图中的两棵树 A 和 B, 由于 A 中有一部分子树的结构和 B 是一样的,因此 B 就是 A的子结构。思路:首先采用一种方式来遍历A树,发现A树的某个节点和B树的根节点的值相等,从这个节点开始遍历是否为A树的一部分。bool IsSame(BinTree* first,BinTree* second)原创 2015-04-29 14:47:47 · 1088 阅读 · 0 评论 -
由二叉树的前序遍历和中序遍历来求后序遍历的结果
假设有棵树,长下面这个样子,它的前序遍历,中序遍历,后续遍历都很容易知道。PreOrder: GDAFEMHZInOrder: ADEFGHMZPostOrder: AEFDHZMG 现在,假设仅仅知道前序和中序遍历,如何求后序遍历呢?比如,已知一棵树的前序遍历是”GDAFEMHZ”,而中序遍历是”ADEFGHMZ”应该原创 2015-01-13 22:52:19 · 1126 阅读 · 0 评论 -
Linus:利用二级指针删除单向链表
Linus大婶在slashdot上回答一些编程爱好者的提问,其中一个人问他什么样的代码是他所喜好的,大婶表述了自己一些观点之后,举了一个指针的例子,解释了什么才是core low-level coding。下面是Linus的教学原文及翻译——“At the opposite end of the spectrum, I actually wish more people underst转载 2013-10-04 16:57:23 · 1341 阅读 · 0 评论 -
二叉树的构造
树是一种非线性的数据结构,树有根节点,子树等概念。二叉树(Binary Tree):每个节点最多有两颗子树,并且子树有左右之分。概念:树的深度,满二叉树,完全二叉树,树的节点树二叉树包括顺序存储和链式存储,这里只说链式存储。二叉树的每个节点和双链表有些类似,但是树的结构要比双链表复杂,在构造树的过程中涉及到递归调用的问题,递归的问题往往是很复杂的问题,因此,这里单独说二叉树的构建。原创 2014-09-15 17:45:36 · 3836 阅读 · 0 评论