
数据结构与算法
文章平均质量分 79
石锅拌饭
新的博客在简书更新,欢迎阅读指正。
展开
-
自己动手写垃圾收集器
之前写过几篇自己动手系列的文章,简要实现了栈,二叉堆,malloc等函数,对于垃圾收集器,一直也有所耳闻。像python中主要使用引用计数手段来管理内存,为了解决循环引用的问题,引入了分代收集和标记-清除方式。当然python中可能产生循环引用的只可能是容器类对象如list,dict,class等,而像int,string是不可能产生循环引用的。当然python中的垃圾收集器实现是比较复杂的,我也没翻译 2015-05-17 17:28:54 · 2648 阅读 · 0 评论 -
二叉树问题汇总(1)—基础问题
1、创建二叉搜索树二叉搜索树是排序的二叉树,即左子树的值都不大于根结点,右子树的值都比根结点大。插入结点到一颗二叉搜索树可以使用递归或者非递归方法。使用递归方法代码简单,使用非递归则易于理解。二叉搜索树BST定义:struct node { int data; struct node* left; struct node* right;};二叉搜索树创建结点原创 2012-07-19 21:09:44 · 2310 阅读 · 0 评论 -
二叉树遍历之递归算法
二叉树的遍历算法有多种,典型的有先序遍历、中序遍历、后序遍历以及层序遍历。而且这些遍历的递归算法较为简单,代码很少,容易实现,本文就是汇总二叉树遍历的递归算法,非递归算法将在下一篇文章中进行总结。本文中用到的二叉树实例如下: 3 / \ 9 20 / \ 15 7二叉树定义和辅助函数如下:struct node {原创 2012-07-22 19:31:35 · 13403 阅读 · 3 评论 -
序列化/反序列化二叉树
题目设计一个算法能够实现序列化和反序列化一棵二叉树(注意,不是二叉搜索树BST)。这里的序列化指的是将一棵二叉树保存到文件中,反序列化就是从文件中读取二叉树结点值重构原来的二叉树。思路前一篇文章保存二叉搜索树到文件中 解决了保存一棵二叉搜索树到文件中的问题,但是由于本题目的意思是要把一棵二叉树保存到文件中并从文件中读出重构二叉树。因为二叉树不一定是二叉搜索树,所以前面文章中的原创 2012-07-24 08:48:47 · 16940 阅读 · 0 评论 -
二叉树问题汇总(2)—常见问题
在上一篇二叉树问题汇总(1)中总结了下二叉树的一些基本问题,主要是针对二叉排序树。这篇文章主要汇总二叉树的一些常见的但是难度稍大一点的问题。1、判定二叉树是否存在和为给定值的路径问题:给定一个值,判定二叉树是否存在从根结点到叶结点的路径,其结点的数据之和为该值。比如二叉树如下所示,给定的和为27:则二叉树存在的根结点到叶结点的路径有:path 1: 5 4 11 7原创 2012-07-19 21:43:49 · 2267 阅读 · 0 评论 -
判定一棵二叉树是否是二叉搜索树
问题给定一棵二叉树,判定该二叉树是否是二叉搜索树(Binary Search Tree)?解法1:暴力搜索首先说明一下二叉树和二叉搜索树的区别。二叉树指这样的树结构,它的每个结点的孩子数目最多为2个;二叉搜索树是一种二叉树,但是它有附加的一些约束条件,这些约束条件必须对每个结点都成立:结点node的左子树所有结点的值都小于node的值。结点node的右子树所有结点的原创 2012-07-21 20:18:05 · 23005 阅读 · 5 评论 -
二叉树遍历之非递归算法
在前一篇文章二叉树遍历递归算法对二叉树遍历的递归算法做了总结,这篇文章就来对二叉树遍历的非递归算法做个汇总。还是与上一篇文章一样的顺序,一一汇总先序、中序、后序以及层序遍历的非递归算法。1、先序遍历(非递归算法)先序遍历非递归访问,使用栈即可实现。先序遍历的非递归访问在所有的遍历中算是最简单的了。主要思想就是先将根结点压入栈,然后根结点出栈并访问根结点,而后依次将根结点的右孩子、左原创 2012-07-22 22:30:26 · 33999 阅读 · 21 评论 -
将有序单链表转换为平衡的二叉搜索树
题目:给定一个升序排列的有序单链表,将其转换为一棵平衡的二叉搜索树。分析:单链表的结点结构如下。struct node { int data; struct node *next;};由于单链表升序排列,可以参照前面的文章将有序数组转换为平衡二叉搜索树, 先求的链表中的结点的值保存在数组中,然后采用相同的方法实现,时间复杂度为O(N)。当然也可以不额原创 2012-08-15 08:51:48 · 3340 阅读 · 0 评论 -
二叉树两结点最低公共祖先结点(二)
问题在前面的文章二叉树两结点最低公共祖先结点(一) 中有探讨过这个问题,不过本文考虑的是另外一种二叉树,该二叉树每个结点包含一个指向父结点的指针,根结点的父结点为NULL。其结构如下: struct node { int data; struct node* left; struct node* right;原创 2012-09-03 17:37:22 · 2585 阅读 · 2 评论 -
复杂链表的复制
原文地址:http://zhedahht.blog.163.com/blog/static/254111742010819104710337/题目:有一个复杂链表,其结点除了有一个m_pNext指针指向下一个结点外,还有一个m_pSibling指向链表中的任一结点或者NULL。其结点的C++定义如下: struct ComplexNode{转载 2012-08-28 20:23:36 · 1222 阅读 · 0 评论 -
背包问题汇总
本文主要来源于《背包问题九讲》,我主要选择了比较简单的0-1背包问题和完全背包问题进行汇总,并加入了python代码实现,刚重装系统,手头没有C编译器,汗。一、背包问题概述 背包问题包括0-1背包问题、完全背包问题、部分背包问题等多种变种。其中,最简单的是部分背包问题,它可以采用贪心法来解决,而其他几种背包问题往往需要动态规划来求解。本文对几种背包问题进行总结,同时给原创 2012-08-26 15:38:54 · 3512 阅读 · 0 评论 -
中序遍历和先序遍历/后序遍历构建二叉树
1、问题给定二叉树的2个遍历序列(如先序+中序,先序+后序,中序+后序等),是否能够根据这2个遍历序列唯一确定二叉树?2、理论分析数据结构的基础知识中重要的一点就是能否根据两种不同遍历序列的组合(有三种:先序+中序,先序+后序,中序+后序),唯一的确定一棵二叉树。然后就是根据二叉树的不同遍历序列(先序、中序、后序),重构二叉树。显然,这三种组合并不是都能唯一确定二叉树的,其原创 2012-07-25 15:02:23 · 29729 阅读 · 13 评论 -
怎样写一个拼写检查器
怎样写一个拼写检查器 Peter Norvig翻译: Eric You XU原文地址:http://blog.youxu.info/spell-correct.html上个星期, 我的两个朋友 Dean 和 Bill 分别告诉我说他们对 Google 的快速高质量的拼写检查工具感到惊奇. 比如说在搜索的时候键入 [speling], 在不到 0.1 秒的时间内, Goo转载 2013-06-14 17:50:30 · 1977 阅读 · 0 评论 -
二叉树两结点的最低公共祖先结点(一)
题目二叉树结点的定义如下:struct node { int data; struct node* left; struct node* right;};给定二叉树中的两个结点,输出这两个结点的最低公共祖先结点(LCA)。注意,该二叉树不一定是二叉搜索树。比如给定的二叉树如下所示,则可以知道结点1和5的最低公共祖先结点为5,结点4和5的最低公共祖先原创 2012-09-02 23:01:42 · 11573 阅读 · 4 评论 -
二分查找之谜题
一、前言二分查找本身是个简单的算法,但是正是因为其简单,更容易写错。甚至于在二分查找算法刚出现的时候,也是存在bug的(溢出的bug),这个bug直到几十年后才修复(见《编程珠玑》)。本文打算对二分查找算法进行总结,并对由二分查找引申出来的问题进行分析和汇总。若有错误,请不吝赐教。二、二分查找是这样的相信大家都知道二分查找的基本算法,如下所示,这就是二分查找算法:int b原创 2012-08-19 16:19:04 · 1411 阅读 · 0 评论 -
随机算法全面总结
随机算法涉及大量概率论知识,有时候难得去仔细看推导过程,当然能够完全了解推导的过程自然是有好处的,如果不了解推导过程,至少记住结论也是必要的。本文总结最常见的一些随机算法的题目,也当作面试的准备工作吧。需要说明的是,这里用到的随机函数都假定它能随机的产生范围[a,b]内的整数,即产生每个整数的概率相等。(虽然在实际中并不一定能实现,不过,谁在乎呢?这个世界都是这么随机)一、随机排列数组原创 2012-08-29 16:21:27 · 17463 阅读 · 0 评论 -
找出二叉树中最大的子树,且子树为二叉搜索树
题目找出二叉树中最大的子树,该子树为二叉搜索树。所谓最大的子树就是指结点数目最多的子树。分析该题目是要找出二叉树中最大的子树,该子树必须是二叉搜索树(BST)。子树的概念需要重点关注一下,以下面一棵二叉树为例 ____10____ / \ __5_ 15_ / \原创 2012-10-05 22:16:09 · 4115 阅读 · 0 评论 -
自己动手写内存分配函数malloc
一、关于malloc很早就想写这篇文章了,一直拖着没有写,是想写个更完善的版本,不过最近确实没有太多时间去考虑一个很完整的版本,只有先把这个简单的版本写出来了。据说在微软今年招实习生的时候面过这个题目。malloc()是C语言中动态存储管理的一组标准库函数之一,其作用就是从内存的动态存储区(堆)中分配一个长度为size的连续内存空间。参数为一个无符号的整数,返回值则是指向所分配的连续存储空原创 2012-09-13 21:51:37 · 8387 阅读 · 1 评论 -
自己动手写二叉堆
一、二叉堆概念二叉堆一种数组对象,可以被视为一棵完全二叉树,树中每个结点和数组中存放该结点值的那个元素对应。树的每一层都是填满的,最后一层除外。表示堆的数组有两个属性对象,其中length[A]表示数组A中的元素个数,而heap-size[A]则表示存放在A中的堆的元素个数。heap-size[A]int parent(int i) { return i/2; }int l原创 2012-08-30 22:54:04 · 2205 阅读 · 0 评论 -
二叉搜索树转换成有序的双向循环链表(一)
题目描述给定一棵二叉排序树(BST),将该树转换成一棵双向循环链表。请看下面的图示说明,你可以更清楚的了解题意。BST的结构定义如下:struct node { int data; struct node* left; struct node* right;};typedef struct node Node;原创 2012-09-03 22:46:53 · 3558 阅读 · 0 评论 -
组合算法面试题
组合算法题往往有多个变种,如求一个集合的全部子集以及部分组合问题,这篇文章对这些常见的面试题做个汇总,权当做个记录,以免自己哪天忘了,难得到网路上去找。一、求一个集合的全部子集题目:给定一个集合s={a, b, c, d},试给出一个算法输出该集合的除了空集之外的全部子集。分析:我们知道,一个集合的子集数目跟它的元素数目有关,集合元素数目为n,则子集数目为2^n。如包含两个元素的集合s原创 2012-08-28 17:32:27 · 5735 阅读 · 0 评论 -
二叉搜索树两结点最低公共祖先结点
题目给定一棵二叉搜索树(BST),找出树中两个结点的最低公共祖先结点(LCA)。二叉搜索树结点定义: struct node { int data; struct node* left; struct node* right; }; 如下图为一棵BST,结点2和8的LCA是6,结点4和2的LCA是2原创 2012-09-03 16:29:42 · 2709 阅读 · 2 评论 -
有序的循环链表中插入结点
题目给定一个有序的循环链表,在其中插入一个值,保持该循环链表依然有序。分析首先看下循环链表的结构,如下图所示为一个循环链表,其尾结点指向头结点,从而形成一个循环。给定的链表结点可以是链表任意一个结点,这个结点不一定是链表头结点,从而这也增加了该题的难度。此时若是要在链表中插入4,则插入后的链表如下所示:可以看到插入4后,链表依然有序。在解决这个问题前,先来看一个原创 2012-08-17 21:43:37 · 3927 阅读 · 0 评论 -
链表逆序算法
问题:给定一个链表,请将其逆序。即如果链表原来为1->2->3->4->5->null,逆序后为5->4->3->2->1->null.解法1:迭代算法迭代算法效率较高,但是代码比递归算法略长。递归算法虽然代码量更少,但是难度也稍大,不细心容易写错。迭代算法的思想就是遍历链表,改变链表节点next指向,遍历完成,链表逆序也就完成了。代码如下:struct node {原创 2012-07-17 10:20:36 · 7282 阅读 · 0 评论 -
经典shell面试题整理
一、取出/etc/passwd文件中shell出现的次数问题:下面是一个/etc/passwd文件的部分内容。题目要求取出shell并统计次数,shell是指后面的/bin/bash,/sbin/nologin等,如下面/bin/bash出现12次,/sbin/nologin出现3次。hyn:x:525:500::/home/hyn:/bin/bashljlxx:x:526:500::/原创 2012-07-31 16:03:21 · 12917 阅读 · 5 评论 -
腾讯的一道面试题—不用除法求数字乘积
题目:已知一个包含N个元素的数组A[N],试求出这样一个数组OUTPUT[N],其中OUTPUT[I]的值为数组A中除了A[i]的其他所有元素的乘积。注意,不能使用除法。时间复杂度必须为O(N)。例如OUTPUT[0]的值为A[1]*A[2]...A[N], OUTPUT[1]的值为A[0]*A[2]...A[N]。假定数组A={4, 3, 2, 1, 2},则OUTPUT={12,原创 2012-07-31 21:26:38 · 4106 阅读 · 3 评论 -
整数分解使得积最大
题目:给一个数n,你可以将这个数拆成任意个整数之和。找出在所有的拆分方式中,拆出来的所有的数的积的最大值(也包括只拆成一个数,如2拆成2最大)。如 n = 6, 可以拆成 3 * 3 = 9 2 * 4 = 82 * 2 * 2 = 8 1 * 1 * 4 = 41 * 1 * 2 * 2 = 4 ...最大值为9。分原创 2012-08-14 19:16:25 · 2533 阅读 · 0 评论 -
翻转句子中单词的顺序
题目:输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。句子中单词以空格符隔开。为简单起见,标点符号和普通字母一样处理。例如输入“I am a student.”,则输出“student. a am I”。分析:由于编写字符串相关代码能够反映程序员的编程能力和编程习惯,与字符串相关的问题一直是程序员笔试、面试题的热门题目。本题也曾多次受到包括微软在内的大量公司的青睐。转载 2012-07-29 22:07:28 · 1780 阅读 · 1 评论 -
判断一个整数是否是回文数
问题判定一个正整数是否是一个回文数。例如12121是回文数,而1231不是回文数。解法1:转换成字符串再判断要判断一个整数是否是回文数,最自然的想法是把整数转换成一个字符串,然后根据回文的对称特性进行判断。数字转换为字符串可以通过itoa函数实现,判断字符串是否为回文字符串代码如下:bool isPalindrome(string &str){ int b原创 2012-07-29 16:47:15 · 13999 阅读 · 2 评论 -
从一列数中筛除尽可能少的数,使得从左往右看这些数是从小到大再从大到小
问题:从一列数中筛除尽可能少的数使得从左往右看,这些数是从小到大再从大到小的(网易)。解法:这是双端 LIS 问题,用 DP 的思想可解,目标规划函数 max{ b[i] + c[i] }, 其中 b[i] 为从左到右, 0 ~ i 个数之间满足递增的数字个数; c[i] 为从右到左, n-1 ~ i 个数之间满足递增的数字个数。最后结果为 n - max + 1。其中 DP 的时候,可以转载 2012-07-29 15:52:47 · 3771 阅读 · 1 评论 -
输出链表倒数第K个结点
题目描述:输入一个单向链表,输出该链表中倒数第k个结点。分析:方法1:要输出链表中的倒数第K个结点,最自然的想法是先求出链表的长度N,然后从头遍历链表输出链表的第N-K+1个结点即可。注意本题数字从1计数,也就是说倒数第1个节点是链表最后一个结点。例如链表长度为4,需要输出倒数第2个结点,则我们只需要从头开始输出链表第3个结点即可。该思路代码如下:struct node原创 2012-08-17 15:26:43 · 4853 阅读 · 10 评论 -
链表复制算法
问题已知一个简单链表,请复制链表并返回头结点指针。解法1:遍历算法从头开始遍历原链表,依次复制链表各个节点。结点定义如下:struct node { int data; struct node* next;};typedef struct node* pNode;创建新结点newNode代码:pNode newNode(int data)原创 2012-07-18 20:26:57 · 6881 阅读 · 0 评论 -
递归面试题汇总
一、前言找工作面试时最喜欢问的是算法题,虽然我觉得有些取巧的算法题只是跟刷题量有关。但是为了找工作不得不加强算法,特别是基础算法,这是一个人基本功的体现。《算法导论》是不错的教材,不过大部头看起来确实需要发时间,到现在还只是大略看了一遍,很多推导过程没细心看下来,深以为憾,以后有时间还是要猛补。算法题中最能体现算法精髓的则非递归莫属了,我对递归一直总觉得是一知半解,为了加深自己的理原创 2012-08-27 21:30:31 · 9268 阅读 · 5 评论 -
将有序数组转换为平衡二叉搜索树
问题给定一个有序数组,数组元素升序排列,试将该数组转换为一棵平衡二叉搜索树(Balanced Binary Search Tree)。 思路这个问题用递归很容易解出来。考虑下面一棵二叉搜索树:这是一棵平衡的二叉搜索树,所谓平衡的定义,就是指二叉树的子树高度之差不能超过1。如果要从一个有序数组中选择一个元素作为根结点,应该选择哪个元素呢?我们应该选择有序数组的中间元素作为原创 2012-07-26 08:27:04 · 10451 阅读 · 0 评论 -
寻找第K小的数
前言寻找第K小的数属于顺序统计学范畴,通常我们可以直接在O(NlgN)的时间内找到第K小的数,使用归并排序或者堆排序对输入数据按从小到大进行排序,然后选择第K个即可。然而,我们还有更好的算法。一、热身—最大值和最小值首先来看一个简单的问题,在一个有n个元素的集合中,需要多少次比较才能确定其最小值呢?这可以很容易退出需要n-1次这个上界。伪代码如下所示:MINIMUM(A原创 2012-08-31 17:15:08 · 12539 阅读 · 0 评论 -
保存二叉搜索树到文件中
问题:设计一个算法,将一棵二叉搜索树(Binary Search Tree,BST)保存到文件中,需要能够从文件中恢复原来的二叉搜索树。注意算法的时空复杂度。思路:二叉树遍历算法有先序遍历、中序遍历、后序遍历算法等。但是它们中间只有一种遍历算法符合题目条件,用于保存BST到文件中并从文件中恢复原来的BST。假定我们要保存的BST如下: _ 30_ /原创 2012-07-23 11:28:10 · 7965 阅读 · 1 评论 -
最长递增子序列
问题给定一个长度为N的数组,找出一个最长的单调自增子序列(不一定连续,但是顺序不能乱)。例如:给定一个长度为6的数组A{5, 6, 7, 1, 2, 8},则其最长的单调递增子序列为{5,6,7,8},长度为4. 解法1:最长公共子序列法这个问题可以转换为最长公共子序列问题。如例子中的数组A{5,6, 7, 1, 2, 8},则我们排序该数组得到数组A‘{1, 2, 5, 6, 7原创 2012-07-29 15:25:08 · 10972 阅读 · 5 评论 -
最大公约数(Gcd)两种算法(Euclid && Stein)
转载自:http://www.cnblogs.com/drizzlecrj/archive/2007/09/14/892340.html很老的东东了,其实也没啥好整理的,网上很多资料了,就当备用把:-)1. 欧几里德算法和扩展欧几里德算法欧几里德算法 欧几里德算法又称辗转相除法,用于计算两个整数a,b的最大公约数。其计算原理依赖于下面的定理: 定理:gcd(a,b) =转载 2012-08-20 10:30:50 · 1533 阅读 · 0 评论 -
链表合并算法
题目已知两个有序链表,试合并这两个链表,使得合并后的链表仍然有序(注:这两个链表没有公共结点,即不交叉)。分析既然两个链表都是有序的,所以合并它们跟合并两个有序数组没有多少区别,只是链表操作涉及到指针,不能大意。方法一:非递归方法使用2个指针list1和list2分别遍历两个链表,将较小值结点归并到结果链表中。如果有一个链表归并结束后另一个链表还有结点,则把另一个链表剩原创 2012-08-19 20:26:11 · 2248 阅读 · 0 评论 -
链表相交问题
题目:给定两个单向链表的头结点指针,比如为h1和h2,判断这两个链表是否相交。分析:一、先来分析链表不存在环的情况。编程之美和JULY的博文闲话链表追赶问题上对该题都有详述,拿来用了。1.直接循环判断第一个链表的每个节点是否在第二个链表中。但,这种方法的时间复杂度为O(Length(h1) * Length(h2))。显然,我们得找到一种更为有效的方法,至少不能原创 2012-08-17 20:09:13 · 1427 阅读 · 3 评论