剑指Offer(面试题6~7)

面试题6:重建二叉树
题目:输入某二叉树的前序和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。假如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6}。二叉树结点的定义如下:

struct BinaryTreeNode
{
    int                 m_nValue;
    BinaryTreeNode*     m_pLeft;
    BinaryTreeNode*     m_pRight;
};

我们可以写出如下的递归代码根据前序和中序遍历的顺序确定二叉树结构:

BinaryTreeNode* Construct(int* preorder,int* inorder,int length)
{
    if(preorder == NULL || inorder == NULL || length <= 0)
        return NULL;
    return ConstructCore(preorder,preorder+length-1,
                         inorder,inorder+length-1);
}

BinaryTreeNode* ConstructCore
(
 int* startPreorder,int* endPreorder,
 int* startInorder,int*endInorder
)
 {
     //前序遍历序列的第一个数字是根结点的值
     int rootValue = startPreorder[0];
     BinaryTreeNode* root = new BinaryTreeNode();
     root->m_nValue = rootValue;
     root->m_pLeft=root->m_pRight=NULL;

     if(startPreorder == endPreorder)
     {
         if(startInorder == endInorder 
            && *startPreorder == *startInorder)
                return root;
         else
            throw std::exception("Invalid input.");
     }

     //在中序遍历中找到根结点的值
     int* rootInorder = startInorder;
     while(rootInorder<=endInorder && *rootInorder != rootValue)
        ++rootInorder;

     if(rootInorder == endInorder && *rootInorder != rootValue)
        throw std::exception("Invalid input.");

     int leftLength=rootInorder-startInorder;
     int* leftPreorderEnd = startPreorder+leftLength;
     if(leftLength>0)
     {
         //构建左子树
         root->m_pLeft=ConstructCore(startPreorder + 1,
                                     leftPreorderEnd,startInorder,rootInorder-1);
     }
     if(leftLength<endPreorder-startPreorder)
     {
         //构建右子树
         root->m_pRight = ConstructCore(leftPreorderEnd+1,endPreorder,rootInorder+1,endInorder);
     }

     return root;
 }

在函数ConstructCore中,我们先根据前序遍历序列的第一个数字创建根结点,接下来在中序遍历序列中找到根结点的位置,这样就能确定左、右子树结点的数量。在前序遍历和中序遍历的序列中划分了左、右子树结点的值之后,我们就可以递归地调用函数ConstructCore,去分别构建它的左右子树。

面试题7:用两个栈实现队列

题目:用两个栈实现一个队列。队列的声明如下,请实现它的两个函数appendTail和deleteHead,分别完成在队和尾部插入结点和在队列头删除结点的功能。

template <typename T> class CQueue
{
public:
    CQueue(void);
    ~CQueue(void);

    void appendTail(const T& node);
    T deleteHead();

private:
    stack<T> stack1;
    stack<t> stack2;
}

template<typename T> void CQueue<T>::appendTail(const T& element)
{
    stack1.push(element);
}
template<typename T> T CQueue<T>::deleteHead()
{
    if(stack2.size()<=0)
    {
        while(stack1.size()>0)
        {
            T& data =stack1.top();
            stack1.pop();
            stack2.push(data);
        }
    }
    if(stack2.size()==0)
        throw new exception("queue is empty");

    T head = stack2.top();
    stack2.pop();

    return head;
}

参考书籍《剑指Offer》

发布了38 篇原创文章 · 获赞 17 · 访问量 10万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章