随笔分类 -  数据结构

摘要:题目:输入一棵二叉树的根结点,判断该树是不是平衡二叉树。如果某二叉树中任意结点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。例如下图中的二叉树就是一棵平衡二叉树: 1 bool IsBalanced(BinaryTreeNode* pRoot) 2 { 3 if(pRoot == NULL) 4 return true; 5 6 int left = TreeDepth(pRoot->m_pLeft); 7 int right = TreeDepth(pRoot->m_pRight); 8 int diff = left - rig... 阅读全文
posted @ 2012-08-12 15:54 wolenski 阅读(306) 评论(0) 推荐(0)
摘要:题目:两个单向链表,找出它们的第一个公共结点。链表的结点定义为:struct ListNode{ int m_nKey; ListNode* m_pNext;};分析:这是一道微软的面试题。微软非常喜欢与链表相关的题目,因此在微软的面试题中,链表出现的概率相当高。如果两个单向链表有公共的结点,也就是说两个链表从某一结点开始,它们的m_pNext都指向同一个结点。但由于是单向链表的结点,每个结点只有一个m_pNext,因此从第一个公共结点开始,之后它们所有结点都是重合的,不可能再出现分叉。所以,两个有公共结点而部分重合的链表,拓扑形状看起来像一个Y,而不可... 阅读全文
posted @ 2012-08-06 17:03 wolenski 阅读(187) 评论(0) 推荐(0)
摘要:题目:给定链表的头指针和一个结点指针,在O(1)时间删除该结点。链表结点的定义如下:struct ListNode{ int m_nKey; ListNode* m_pNext;};函数的声明如下:void DeleteNode(ListNode* pListHead, ListNode* pToBeDeleted);分析:这是一道广为流传的Google面试题,能有效考察我们的编程基本功,还能考察我们的反应速度,更重要的是,还能考察我们对时间复杂度的理解。在链表中删除一个结点,最常规的做法是从链表的头结点开始,顺序查找要删除的结点,找到之后再删除。由于需要顺... 阅读全文
posted @ 2012-08-06 16:29 wolenski 阅读(181) 评论(0) 推荐(0)
摘要:题目:输入一个链表的头结点,从尾到头反过来输出每个结点的值。链表结点定义如下:struct ListNode{ int m_nKey; ListNode* m_pNext;};分析:这是一道很有意思的面试题。该题以及它的变体经常出现在各大公司的面试、笔试题中。看到这道题后,第一反应是从头到尾输出比较简单。于是很自然地想到把链表中链接结点的指针反转过来,改变链表的方向。然后就可以从头到尾输出了。反转链表的算法详见本人面试题精选系列的第19题,在此不再细述。但该方法需要额外的操作,应该还有更好的方法。接下来的想法是从头到尾遍历链表,每经过一个结点的时候,把该结点放到... 阅读全文
posted @ 2012-08-06 15:24 wolenski 阅读(219) 评论(0) 推荐(0)
摘要:题目:输入一棵二元树的根结点,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。例如:输入二元树:10/\6 14/ / \41216输出该树的深度3。二元树的结点定义如下:struct SBinaryTreeNode // a node of the binary tree{ int m_nValue; // value of node SBinaryTreeNode *m_pLeft; // left child of node SBinaryTreeNode *m_pRi... 阅读全文
posted @ 2012-08-06 10:37 wolenski 阅读(220) 评论(0) 推荐(0)
摘要:题目:输入一个链表的头结点,反转该链表,并返回反转后链表的头结点。链表结点定义如下:1 struct ListNode2 {3 int m_nKey;4 ListNode* m_pNext;5 };分析:这是一道广为流传的微软面试题。由于这道题能够很好的反应出程序员思维是否严密,在微软之后已经有很多公司在面试时采用了这道题。为了正确地反转一个链表,需要调整指针的指向。与指针操作相关代码总是容易出错的,因此最好在动手写程序之前作全面的分析。在面试的时候不急于动手而是一开始做仔细的分析和设计,将会给面试官留下很好的印象,因为在实际的软件开发中,设计的时间总是比写... 阅读全文
posted @ 2012-07-11 10:20 wolenski 阅读(170) 评论(0) 推荐(0)
摘要:题目:某队列的声明如下: 1 template<typename T> class CQueue 2 { 3 public: 4 CQueue() {} 5 ~CQueue() {} 6 7 void appendTail(const T& node); // append a element to tail 8 void deleteHead(); // remove a element from head 9 10 private:11 T> m_stack1;12 T> m_stack2... 阅读全文
posted @ 2012-07-11 10:11 wolenski 阅读(215) 评论(0) 推荐(0)
摘要:题目:输入一颗二元树,从上往下按层打印树的每个结点,同一层中按照从左往右的顺序打印。例如输入8/\610 /\/\57911输出861057911。分析:这曾是微软的一道面试题。这道题实质上是要求遍历一棵二元树,只不过不是我们熟悉的前序、中序或者后序遍历。我们从树的根结点开始分析。自然先应该打印根结点8,同时为了下次能够打印8的两个子结点,我们应该在遍历到8时把子结点6和10保存到一个数据容器中。现在数据容器中就有两个元素6和10了。按照从左往右的要求,我们先取出6访问。打印6的同时要把6的两个子结点5和7放入数据容器中,此时数据容器中有三个元素10、5和7。接下来我们应该从数据容器中取出结点 阅读全文
posted @ 2012-07-10 09:33 wolenski 阅读(215) 评论(0) 推荐(0)
摘要:题目:输入一颗二元查找树,将该树转换为它的镜像,即在转换后的二元查找树中,左子树的结点都大于右子树的结点。用递归和循环两种方法完成树的镜像转换。例如输入:8/\610/\/\57911输出:8/\106/\/\119 75定义二元查找树的结点为:1 struct BSTreeNode // a node in the binary search tree (BST)2 {3 int m_nValue; // value of node4 BSTreeNode *m_pLeft; // left child of node5 BSTree... 阅读全文
posted @ 2012-07-10 09:25 wolenski 阅读(243) 评论(0) 推荐(0)
摘要:题目:输入一个单向链表,输出该链表中倒数第k个结点。链表的倒数第0个结点为链表的尾指针。链表结点定义如下:1 struct ListNode2 {3 int m_nKey;4 ListNode* m_pNext;5 };分析:为了得到倒数第k个结点,很自然的想法是先走到链表的尾端,再从尾端回溯k步。可是输入的是单向链表,只有从前往后的指针而没有从后往前的指针。因此我们需要打开我们的思路。既然不能从尾结点开始遍历这个链表,我们还是把思路回到头结点上来。假设整个链表有n个结点,那么倒数第k个结点是从头结点开始的第n-k-1个结点(从0开始计数)。如果我们能够得到... 阅读全文
posted @ 2012-07-09 16:37 wolenski 阅读(239) 评论(0) 推荐(0)
摘要:题目:输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果。如果是返回true,否则返回false。例如输入5、7、6、9、11、10、8,由于这一整数序列是如下树的后序遍历结果:8/\610 / \/ \57911因此返回true。如果输入7、4、6、5,没有哪棵树的后序遍历的结果是这个序列,因此返回false。分析:这是一道trilogy的笔试题,主要考查对二元查找树的理解。在后续遍历得到的序列中,最后一个元素为树的根结点。从头开始扫描这个序列,比根结点小的元素都应该位于序列的左半部分;从第一个大于跟结点开始到跟结点前面的一个元素为止,所有元素都应该大于跟结点,因为这部分元素对应 阅读全文
posted @ 2012-07-08 22:42 wolenski 阅读(263) 评论(0) 推荐(0)
摘要:题目:输入一个整数和一棵二元树。从树的根结点开始往下访问一直到叶结点所经过的所有结点形成一条路径。打印出和与输入整数相等的所有路径。例如输入整数22和如下二元树 10 / \ 5 12 / \ 4 7则打印出两条路径:10, 12和10, 5, 7。二元树结点的数据结构定义为:1 struct BinaryTreeNode // a node in the binary tree2 {3 int m_nValue; // value of node4 BinaryTreeNode *m_pLeft; // left child of ... 阅读全文
posted @ 2012-07-08 21:30 wolenski 阅读(172) 评论(0) 推荐(0)
摘要:题目:定义栈的数据结构,要求添加一个min函数,能够得到栈的最小元素。要求函数min、push以及pop的时间复杂度都是O(1)。分析:这是去年google的一道面试题。我看到这道题目时,第一反应就是每次push一个新元素时,将栈里所有逆序元素排序。这样栈顶元素将是最小元素。但由于不能保证最后push进栈的元素最先出栈,这种思路设计的数据结构已经不是一个栈了。在栈里添加一个成员变量存放最小元素(或最小元素的位置)。每次push一个新元素进栈的时候,如果该元素比当前的最小元素还要小,则更新最小元素。乍一看这样思路挺好的。但仔细一想,该思路存在一个重要的问题:如果当前最小元素被pop出去,如何才能 阅读全文
posted @ 2012-07-08 21:19 wolenski 阅读(305) 评论(0) 推荐(0)
摘要:题目:输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。要求不能创建任何新的结点,只调整指针的指向。比如将二元查找树 10 / \ 6 14 / \ / \ 4 8 12 16转换成双向链表4=6=8=10=12=14=16。分析:本题是微软的面试题。很多与树相关的题目都是用递归的思路来解决,本题也不例外。下面我们用两种不同的递归思路来分析。 思路一:当我们到达某一结点准备调整以该结点为根结点的子树时,先调整其左子树将左子树转换成一个排好序的左子链表,再调整其右子树转换右子链表。最近链接左子链表的最右结点(左子树的最大结点)、当前结点和右子链表的最左结点(右子树的最小结点)... 阅读全文
posted @ 2012-07-08 21:07 wolenski 阅读(2064) 评论(0) 推荐(0)