剑指Offer(面试题22~24)

面试题22:栈的压入、弹出序列

题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1、2、3、4、5是某栈的压入顺序,序列4、5、3、2、1是该压栈序列对应的一个弹出序列,但4、3、5、1、2就不可能是该栈序列的弹出序列。

判断一个序列是不是栈的弹出序列的规律:如果下一个弹出的数字刚好是栈顶数字,那么直接弹出。如果下一个弹出的数字不在栈顶,我们把压栈序列中还没有入栈的数字压入辅助栈,直到把下一个需要弹出的数字压入栈顶为止。如果所有的数字都压入栈了仍然没有找到下一个弹出的数字,那么该序列不可能是一个弹出序列。

bool IsPopOrder(const int* pPush,const int* pPop,int nLength)
{
    bool bPossible = false;

    if(pPush != NULL && pPop != NULL && nLength > 0)
    {
        const int* pNextPush = pPush;
        const int* pNextPop = pPop;

        std::stack<int> stackData;

        while(pNextPop - pPop < nLength)
        {
            while(stackData.empty() || stackData.top() != *pNextPop)
            {
                if(pNextPush - pPush == nLength)
                    break;
                stackData.push(*pNextPush);

                pNextPush++;
            }

            if(stackData.top() != *pNextPop)
                break;

            stackData.pop();
            pNextPop++;
        }

        if(stackData.empty() && pNextPop - pPop == nLength)
            bPossible = true;
    }

    return bPossible;
}

面试题23:从上往下打印二叉树

题目:从上往下打印出二叉树的每个结点,同一层的结点按照从左到右的顺序打印。例如输入图4.5中的二叉树,则依次打印出8、6、10、5、7、9、11。
二叉树结点的定义如下:

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

从上到下打印二叉树的规律:每次打印一个结点的时候,如果该结点有子结点,则把该结点的子结点放到一个队列的末尾。接下来到队列的头部取出最早进入队列的结点,重复前面的打印操作,直至队列中所有的结点都被打印出来为止。

void PrintFromTopToBottom(BinaryTreeNode* pTreeRoot)
{
    if(!pTreeRoot)
        return;

    std::deque<BinaryTreeNode *> dequeTreeNode;
    dequeTreeNode.push_back(pTreeRoot);

    while(dequeTreeNode.size())
    {
        BinaryTreeNode *pNode = dequeTreeNode.front();
        dequeTreeNode.pop_front();

        printf("%d",pNode->m_nValue);

        if(pNode->m_pLeft)
            dequeTreeNode.push_back(pNode->m_pLeft);

        if(pNode->m_pRight)
            dequeTreeNode.push_back(pNode->m_pRight);
    }
}

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

题目:输入一个整数数组,判断数组是不是某二叉搜索树的后序遍历的结果。如果是则返回true,否则返回false。假设输入的数组的任意两个数字都互不相同。

在后序遍历得到的序列中,最后一个数字是树的根结点的值。数组中前面的数字可以分为两部分:第一部分是左子树结点的值,它们都比根结点的值小;第二部分是右子树结点的值,它们都比根结点的值大。

bool VerifySquenceOfBst(int sequence[],int length)
{
    if(sequence == NULL || length <= 0)
        return false;

    int root = sequence[length -1];

    //在二叉搜索树中左子树的结点小于根结点
    int i = 0;
    for(;i < length -1;++i)
    {
        if(sequence[i] > root)
            break;
    }

    //在二叉搜索树中右子树的结点大于根结点
    int j=i;
    for(;j< length-1;++j)
    {
        if(sequence[j] < root)
            return false;
    }

    //判断左子树是不是二叉搜索树
    bool left = true;
    if(i > 0)
        left=VerifySquenceOfBst(sequence,i);

    //判断右子树是不是二叉搜索树
    bool right = true;
    if(i < length -1 )
        right = VerifySquenceOfBst(sequence+i,length-i-1);

    return (left && right);

}

参考资料《剑指Offer》

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