剑指offer题目汇总(三)

来源:互联网 发布:手机克隆软件 编辑:程序博客网 时间:2024/05/16 05:21

剑指offer 面试题 21-30

作者代码下载地址 https://github.com/zhedahht/CodingInterviewChinese2

面试题21:调整数组顺序使奇数位于偶数前面

题目:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。

// ====================方法一====================void ReorderOddEven_1(int *pData, unsigned int length){    if(pData == nullptr || length == 0)        return;    int *pBegin = pData;    int *pEnd = pData + length - 1;    while(pBegin < pEnd)    {        // 向后移动pBegin,直到它指向偶数        while(pBegin < pEnd && (*pBegin & 0x1) != 0)            pBegin ++;        // 向前移动pEnd,直到它指向奇数        while(pBegin < pEnd && (*pEnd & 0x1) == 0)            pEnd --;        if(pBegin < pEnd)        {            int temp = *pBegin;            *pBegin = *pEnd;            *pEnd = temp;        }    }}// ====================方法二====================void ReorderOddEven_2(int *pData, unsigned int length){    Reorder(pData, length, isEven);}void Reorder(int *pData, unsigned int length, bool (*func)(int)){    if(pData == nullptr || length == 0)        return;    int *pBegin = pData;    int *pEnd = pData + length - 1;    while(pBegin < pEnd)    {        // 向后移动pBegin        while(pBegin < pEnd && !func(*pBegin))            pBegin ++;        // 向前移动pEnd        while(pBegin < pEnd && func(*pEnd))            pEnd --;        if(pBegin < pEnd)        {            int temp = *pBegin;            *pBegin = *pEnd;            *pEnd = temp;        }    }}bool isEven(int n){    return (n & 1) == 0;}

面试题22:链表中倒数第k个结点

题目:输入一个链表,输出该链表中倒数第k个结点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾结点是倒数第1个结点。例如一个链表有6个结点,从头结点开始它们的值依次是1、2、3、4、5、6。这个链表的倒数第3个结点是值为4的结点。

ListNode* FindKthToTail(ListNode* pListHead, unsigned int k){    if(pListHead == nullptr || k == 0)        return nullptr;    ListNode *pAhead = pListHead;    ListNode *pBehind = nullptr;    for(unsigned int i = 0; i < k - 1; ++ i)    {        if(pAhead->m_pNext != nullptr)            pAhead = pAhead->m_pNext;        else        {            return nullptr;        }    }    pBehind = pListHead;    while(pAhead->m_pNext != nullptr)    {        pAhead = pAhead->m_pNext;        pBehind = pBehind->m_pNext;    }    return pBehind;}

面试题23:链表中环的入口结点

题目:一个链表中包含环,如何找出环的入口结点?例如,在图3.8的链表中,环的入口结点是结点3。

ListNode* MeetingNode(ListNode* pHead){    if(pHead == nullptr)        return nullptr;    ListNode* pSlow = pHead->m_pNext;    if(pSlow == nullptr)        return nullptr;    ListNode* pFast = pSlow->m_pNext;    while(pFast != nullptr && pSlow != nullptr)    {        if(pFast == pSlow)            return pFast;        pSlow = pSlow->m_pNext;        pFast = pFast->m_pNext;        if(pFast != nullptr)            pFast = pFast->m_pNext;    }    return nullptr;}ListNode* EntryNodeOfLoop(ListNode* pHead){    ListNode* meetingNode = MeetingNode(pHead);    if(meetingNode == nullptr)        return nullptr;    // 得到环中结点的数目    int nodesInLoop = 1;    ListNode* pNode1 = meetingNode;    while(pNode1->m_pNext != meetingNode)    {        pNode1 = pNode1->m_pNext;        ++nodesInLoop;    }    // 先移动pNode1,次数为环中结点的数目    pNode1 = pHead;    for(int i = 0; i < nodesInLoop; ++i)        pNode1 = pNode1->m_pNext;    // 再移动pNode1和pNode2    ListNode* pNode2 = pHead;    while(pNode1 != pNode2)    {        pNode1 = pNode1->m_pNext;        pNode2 = pNode2->m_pNext;    }    return pNode1;}

面试题24:反转链表

题目:定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点。

ListNode* ReverseList(ListNode* pHead){    ListNode* pReversedHead = nullptr;    ListNode* pNode = pHead;    ListNode* pPrev = nullptr;    while(pNode != nullptr)    {        ListNode* pNext = pNode->m_pNext;        if(pNext == nullptr)            pReversedHead = pNode;        pNode->m_pNext = pPrev;        pPrev = pNode;        pNode = pNext;    }    return pReversedHead;}

面试题25:合并两个排序的链表

题目:输入两个递增排序的链表,合并这两个链表并使新链表中的结点仍然是按照递增排序的。例如输入图3.11中的链表1和链表2,则合并之后的升序链表如链表3所示。

ListNode* Merge(ListNode* pHead1, ListNode* pHead2){    if(pHead1 == nullptr)        return pHead2;    else if(pHead2 == nullptr)        return pHead1;    ListNode* pMergedHead = nullptr;    if(pHead1->m_nValue < pHead2->m_nValue)    {        pMergedHead = pHead1;        pMergedHead->m_pNext = Merge(pHead1->m_pNext, pHead2);    }    else    {        pMergedHead = pHead2;        pMergedHead->m_pNext = Merge(pHead1, pHead2->m_pNext);    }    return pMergedHead;}

面试题26:树的子结构

题目:输入两棵二叉树A和B,判断B是不是A的子结构。

struct BinaryTreeNode{    double                 m_dbValue;    BinaryTreeNode*        m_pLeft;    BinaryTreeNode*        m_pRight;};bool DoesTree1HaveTree2(BinaryTreeNode* pRoot1, BinaryTreeNode* pRoot2);bool Equal(double num1, double num2);bool HasSubtree(BinaryTreeNode* pRoot1, BinaryTreeNode* pRoot2){    bool result = false;    if(pRoot1 != nullptr && pRoot2 != nullptr)    {        if(Equal(pRoot1->m_dbValue, pRoot2->m_dbValue))            result = DoesTree1HaveTree2(pRoot1, pRoot2);        if(!result)            result = HasSubtree(pRoot1->m_pLeft, pRoot2);        if(!result)            result = HasSubtree(pRoot1->m_pRight, pRoot2);    }    return result;}bool DoesTree1HaveTree2(BinaryTreeNode* pRoot1, BinaryTreeNode* pRoot2){    if(pRoot2 == nullptr)        return true;    if(pRoot1 == nullptr)        return false;    if(!Equal(pRoot1->m_dbValue, pRoot2->m_dbValue))        return false;    return DoesTree1HaveTree2(pRoot1->m_pLeft, pRoot2->m_pLeft) &&        DoesTree1HaveTree2(pRoot1->m_pRight, pRoot2->m_pRight);}bool Equal(double num1, double num2){    if((num1 - num2 > -0.0000001) && (num1 - num2 < 0.0000001))        return true;    else        return false;}

面试题27:二叉树的镜像

题目:请完成一个函数,输入一个二叉树,该函数输出它的镜像。

void MirrorRecursively(BinaryTreeNode *pNode){    if((pNode == nullptr) || (pNode->m_pLeft == nullptr && pNode->m_pRight))        return;    BinaryTreeNode *pTemp = pNode->m_pLeft;    pNode->m_pLeft = pNode->m_pRight;    pNode->m_pRight = pTemp;    if(pNode->m_pLeft)        MirrorRecursively(pNode->m_pLeft);    if(pNode->m_pRight)        MirrorRecursively(pNode->m_pRight);}void MirrorIteratively(BinaryTreeNode* pRoot){    if(pRoot == nullptr)        return;    std::stack<BinaryTreeNode*> stackTreeNode;    stackTreeNode.push(pRoot);    while(stackTreeNode.size() > 0)    {        BinaryTreeNode *pNode = stackTreeNode.top();        stackTreeNode.pop();        BinaryTreeNode *pTemp = pNode->m_pLeft;        pNode->m_pLeft = pNode->m_pRight;        pNode->m_pRight = pTemp;        if(pNode->m_pLeft)            stackTreeNode.push(pNode->m_pLeft);        if(pNode->m_pRight)            stackTreeNode.push(pNode->m_pRight);    }}

面试题28:对称的二叉树

题目:请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和
它的镜像一样,那么它是对称的。

bool isSymmetrical(BinaryTreeNode* pRoot1, BinaryTreeNode* pRoot2);bool isSymmetrical(BinaryTreeNode* pRoot){    return isSymmetrical(pRoot, pRoot);}bool isSymmetrical(BinaryTreeNode* pRoot1, BinaryTreeNode* pRoot2){    if(pRoot1 == nullptr && pRoot2 == nullptr)        return true;    if(pRoot1 == nullptr || pRoot2 == nullptr)        return false;    if(pRoot1->m_nValue != pRoot2->m_nValue)        return false;    return isSymmetrical(pRoot1->m_pLeft, pRoot2->m_pRight)        && isSymmetrical(pRoot1->m_pRight, pRoot2->m_pLeft);}

面试题29:顺时针打印矩阵

题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。

void PrintMatrixInCircle(int** numbers, int columns, int rows, int start);void printNumber(int number);void PrintMatrixClockwisely(int** numbers, int columns, int rows){    if(numbers == nullptr || columns <= 0 || rows <= 0)        return;    int start = 0;    while(columns > start * 2 && rows > start * 2)    {        PrintMatrixInCircle(numbers, columns, rows, start);        ++start;    }}void PrintMatrixInCircle(int** numbers, int columns, int rows, int start){    int endX = columns - 1 - start;    int endY = rows - 1 - start;    // 从左到右打印一行    for(int i = start; i <= endX; ++i)    {        int number = numbers[start][i];        printNumber(number);    }    // 从上到下打印一列    if(start < endY)    {        for(int i = start + 1; i <= endY; ++i)        {            int number = numbers[i][endX];            printNumber(number);        }    }    // 从右到左打印一行    if(start < endX && start < endY)    {        for(int i = endX - 1; i >= start; --i)        {            int number = numbers[endY][i];            printNumber(number);        }    }    // 从下到上打印一行    if(start < endX && start < endY - 1)    {        for(int i = endY - 1; i >= start + 1; --i)        {            int number = numbers[i][start];            printNumber(number);        }    }}void printNumber(int number){    printf("%d\t", number);}

面试题30:包含min函数的栈

题目:定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的min函数。在该栈中,调用min、push及pop的时间复杂度都是O(1)。

template <typename T> class StackWithMin{public:    StackWithMin() {}    virtual ~StackWithMin() {}    T& top();    const T& top() const;    void push(const T& value);    void pop();    const T& min() const;    bool empty() const;    size_t size() const;private:    std::stack<T>   m_data;     // 数据栈,存放栈的所有元素    std::stack<T>   m_min;      // 辅助栈,存放栈的最小元素};template <typename T> void StackWithMin<T>::push(const T& value){    // 把新元素添加到辅助栈    m_data.push(value);    // 当新元素比之前的最小元素小时,把新元素插入辅助栈里;    // 否则把之前的最小元素重复插入辅助栈里    if(m_min.size() == 0 || value < m_min.top())        m_min.push(value);    else        m_min.push(m_min.top());}template <typename T> void StackWithMin<T>::pop(){    assert(m_data.size() > 0 && m_min.size() > 0);    m_data.pop();    m_min.pop();}template <typename T> const T& StackWithMin<T>::min() const{    assert(m_data.size() > 0 && m_min.size() > 0);    return m_min.top();}template <typename T> T& StackWithMin<T>::top(){    return m_data.top();}template <typename T> const T& StackWithMin<T>::top() const{    return m_data.top();}template <typename T> bool StackWithMin<T>::empty() const{    return m_data.empty();}template <typename T> size_t StackWithMin<T>::size() const{    return m_data.size();}
0 0
原创粉丝点击