《剑指offer》笔记-第4章(3)

来源:互联网 发布:易语言qq空间秒赞源码 编辑:程序博客网 时间:2024/05/22 13:41

面试题33:二叉搜索树的后序遍历序列

       输入一个整数数组,判断该数组是不是某二叉树搜索树的后序遍历结果。假设输入数组的任意两个数字不相等。{7,4,6,5}返回false,该序列没有二叉树与之对应;

测试用例:

       功能测试:输入的后序遍历所对应的二叉树是:完全二叉树、所有节点只有左/右子树的二叉树;输入序列应返回false;

       特殊输入:序列是null;序列只有一个数;

分析:

       1.    二叉搜索树的左子树节点都比根节点小,右子树节点都比根节点大;

       2.    序列的最后一个数是二叉搜索树的根节点;从序列的第一个数开始,依次所有比根节点小的数都是左子树的节点,剩下的应该都比根结点大,是右子树的节点;否则(即不是依次比根节点小或者大如7 5 6)不是一棵二叉搜索树;

       3.    递归实现;本题关键是找到后序遍历的规律;

       如果面试题要求处理一棵二叉树的遍历序列,则可以先找到二叉树的根节点,在基于根节点把整棵树的比那里序列拆分成左子树和右子树序列,再递归地处理两个子序列。

面试题34:二叉树中和为某一值的路径

       输入一棵二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径。从树的根节点开始往下一直到叶节点所经过的节点形成一条路径。

测试用例:

       功能测试:二叉树中有0条/1条/多条符合要求的路径;

       特殊输入:二叉树根节点是null;

分析:

       1.    需要一个辅助栈来存储路径path;

       2.    前序遍历访问某个节点,当节点是叶节点并且路径中节点值的和等于输入整数,则符合要求,打印出来;

       3.    如果节点不是叶节点,则递归遍历它的子节点;

       4.    递归函数自动回到它的父节点,返回前path要弹出当前节点;

4.4分解让复杂问题简单化

       分解复杂问题,每一步解决一个小问题,可以每一步定义一个函数;

       分治法:各个击破思想,把分解后的小问题各个解决,吧小问题的解决方案结合起来解决大问题,通常可用递归实现;

面试题35:复杂链表的复制

       实现函数ComplexListNode* Clone(ComplexListNode* pHead),复制一个复杂链表。复杂链表定义如下:其中m_pNext指向下一个节点,m_pSibling指向链表中任意节点或者null;

Struct ComplexListNode{

int m_nValue;

ComplexListNode* m_pNext;

ComplexListNode* m_pSibling;

}

测试用例:

     功能测试:节点中m_pSibling指向自身;两个节点的m_pSibling成环状;

     特殊输入:链表头为null;链表只有一个节点;

分析:

       1.    最初想到第一步复制原始链表的节点,用m_pNext指针连接起来,第二步设置m_pSibling,问题是如何设置m_pSibling指针即如何定位m_pSibling的位置;

       2.    通过从链表头开始查找来定位,每设置一个m_pSibling需要O(n)步,这种方法时间复杂度是O(n^2);

       3.    以空间换时间,将新旧节点的位置信息<old_pos,new_pos>的配对放到哈希表中,这样时间复杂度是O(n);

       4.    有一种方法不用额外空间,也可以实现O(n)时间的复杂度,分3步:

       5.    第一步,复制链表中的每个节点N并创建新节点N’,并将N’连接到N的后面,链表从ABCD变为A A’B B’C C’D D’

       6.    第二步,设置m_pSibling,例如原来A指向C,设置A’指向C’

       7.    第三步,将长链拆分成两个链;奇数位置的节点组成原始链表,偶数位置的节点组成新链表;

原创粉丝点击