剑指Offer第26题(复杂链表的复制)

本文详细介绍了复杂链表的复制算法,包括使用分治法处理的两种方法。第一种方法利用辅助空间,通过映射存储原节点及其拷贝节点来完成复制;第二种方法则在原链表中每个节点后插入拷贝节点,再调整sibling指针完成分离。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

(本博客旨在个人总结回顾)

题目描述:

       请实现函数ComplexListNode* Clone(ComplexListNode* pHead),复制一个复杂链表。在复杂链表中,每个结点除了有一个m_pNext指针指向下一个结点外,还有一个m_pSibling指向链表中的任意结点或者NULL.

       结点的C++定义如下:

struct ComplexListNode
{
    int                    m_nValue;
    ComplexListNode*       m_pNext;
    ComplexListNode*       m_pSibling;
};

解题思路:

解法一:

使用分治法处理题目:①先简单拷贝链表,并存储链表各个结点及其对应的各个拷贝结点。②将简单拷贝的链表每个结点m_pSibling指向其对应拷贝的结点。

此方法时间复杂度为O(n),并且需要辅助空间。可使用map映射存储原结点及其拷贝结点。

完整代码:


#include "stdafx.h"
#include <iostream>
#include <map>
using namespace std;

struct ComplexListNode
{
    int                    m_nValue;
    ComplexListNode*       m_pNext;
    ComplexListNode*       m_pSibling;
};

/*
* @name   InsertListForEachNode
* @brief  在链表每个结点之后插入每个结点的拷贝
* @param  [in] ComplexListNode * pHead
* @return void
*/
void InsertListForEachNode(ComplexListNode* pHead)
{
    if (pHead != NULL)
    {
        ComplexListNode* pNext = NULL;
        ComplexListNode* pTmp = NULL;
        while (pHead != NULL)
        {
            pNext = pHead->m_pNext;

            //简单拷贝结点并插入
            pTmp = new ComplexListNode();
            pTmp->m_nValue = pHead->m_nValue;
            pTmp->m_pSibling = pHead->m_pSibling;
            pTmp->m_pNext = pNext;
            pHead->m_pNext = pTmp;

            pHead = pNext;
        }
    }
}

/*
* @name   GetResultList
* @brief  将插入后的链表m_bSibling指向下一个位置,并分离出目标链表
* @param  [in] ComplexListNode * pHead
* @return ComplexListNode* 分离出拷贝的链表
*/
ComplexListNode* GetResultList(ComplexListNode* pHead)
{
    ComplexListNode* pResult = NULL;
    if (NULL != pHead)
    {
        ComplexListNode* pResultIndex = NULL;
        ComplexListNode* pNext = NULL;
        bool bCloneNode = false;
        while (NULL != pHead)
        {
            pNext = pHead->m_pNext;
            if (bCloneNode)
            {
                if (NULL != pHead->m_pSibling)
                {
                    pHead->m_pSibling = pHead->m_pSibling->m_pNext;
                }
                if (NULL == pResultIndex)
                {
                    pResultIndex = pHead;
                    pResult = pResultIndex;
                }
                else
                {
                    pResultIndex->m_pNext = pHead;
                    pResultIndex = pResultIndex->m_pNext;
                }
            }
            else
            {
                if (pHead->m_pNext != NULL)
                {
                    pHead->m_pNext = pHead->m_pNext->m_pNext;
                }                

            }
            bCloneNode = !bCloneNode;
            pHead = pNext;
        }
    }
    return pResult;
}




/*
* @name   Clone
* @brief  复杂链表的复制
* @param  [in] ComplexListNode*  pHead
* @return ComplexListNode*       返回复制链表的头结点
*/
ComplexListNode* Clone(ComplexListNode* pHead)
{
    ComplexListNode* pHeadResult = NULL;
    if (pHead != NULL)
    {
        InsertListForEachNode(pHead);
        pHeadResult = GetResultList(pHead);

    }
    return pHeadResult;
}

int _tmain(int argc, _TCHAR* argv[])
{
    //                ____________________ 
    //                |                  |               
    //                V                  |
    //      A-------->B-------->C-------->D-------->E
    //      |         |         /\                 /\  
    //      |_________|_________|                  |
    //                |____________________________| 
    ComplexListNode* pA = new ComplexListNode();
    pA->m_nValue = 10;

    ComplexListNode* pB = new ComplexListNode();
    pA->m_pNext = pB;
    pB->m_nValue = 20;

    ComplexListNode* pC = new ComplexListNode();
    pB->m_pNext = pC;
    pC->m_nValue = 30;

    ComplexListNode* pD = new ComplexListNode();
    pC->m_pNext = pD;
    pD->m_nValue = 40;

    ComplexListNode* pE = new ComplexListNode();
    pD->m_pNext = pE;
    pE->m_nValue = 50;

    pA->m_pSibling = pC;
    pB->m_pSibling = pE;
    pD->m_pSibling = pB;

    ComplexListNode* pA1 = Clone(pA);
    Clone(NULL);
    Clone(new ComplexListNode());

    system("pause");
    return 0;
}

解法二:

①原链表:实线表示m_pNext,虚线表示m_pSibling,指向NULL不使用线表示。

②在原链表中每一个结点后插入该结点的拷贝结点。

③拷贝结点m_pSibing指向原结点(前一结点)的m_pSibing的下一个结点

④将原结点和拷贝结点分开成原链表和拷贝链表:

 

完整代码:


#include "stdafx.h"
#include <iostream>
#include <map>
using namespace std;

struct ComplexListNode
{
    int                    m_nValue;
    ComplexListNode*       m_pNext;
    ComplexListNode*       m_pSibling;
};

/*
 * @name   InsertListForEachNode
 * @brief  在链表每个结点之后插入每个结点的拷贝
 * @param  [in] ComplexListNode * pHead
 * @return void
 */
void InsertListForEachNode(ComplexListNode* pHead)
{
    if (pHead != NULL)
    {
        ComplexListNode* pNext = NULL;
        ComplexListNode* pTmp = NULL;
        while (pHead != NULL)
        {
            pNext = pHead->m_pNext;

            //简单拷贝结点并插入
            pTmp = new ComplexListNode();
            pTmp->m_nValue = pHead->m_nValue;
            pTmp->m_pSibling = pHead->m_pSibling;
            pTmp->m_pNext = pNext;
            pHead->m_pNext = pTmp;

            pHead = pNext;
        }
    }
}

/*
 * @name   GetResultList
 * @brief  将插入后的链表m_bSibling指向下一个位置,并分离出目标链表
 * @param  [in] ComplexListNode * pHead
 * @return ComplexListNode* 分离出拷贝的链表
 */
ComplexListNode* GetResultList(ComplexListNode* pHead)
{
    ComplexListNode* pResult = NULL;
    if (NULL != pHead)
    {
        ComplexListNode* pResultIndex = NULL;
        bool bCloneNode = false;
        while (NULL != pHead)
        {
            if (bCloneNode)
            {
                if (NULL != pHead->m_pSibling)
                {
                    pHead->m_pSibling = pHead->m_pSibling->m_pNext;
                }                
                if (NULL == pResultIndex)
                {
                    pResultIndex = pHead;
                    pResult = pResultIndex;
                }
                else
                {
                    pResultIndex->m_pNext = pHead;
                    pResultIndex = pResultIndex->m_pNext;
                }
            }
            bCloneNode = !bCloneNode;

            pHead = pHead->m_pNext;
        }
    }
    return pResult;
}




/*
* @name   Clone
* @brief  复杂链表的复制
* @param  [in] ComplexListNode*  pHead
* @return ComplexListNode*       返回复制链表的头结点
*/
ComplexListNode* Clone(ComplexListNode* pHead)
{
    ComplexListNode* pHeadResult = NULL;
    if (pHead != NULL)
    {
        InsertListForEachNode(pHead);
        pHeadResult = GetResultList(pHead);

    }
    return pHeadResult;
}

int _tmain(int argc, _TCHAR* argv[])
{
    //                ____________________ 
    //                |                  |               
    //                V                  |
    //      A-------->B-------->C-------->D-------->E
    //      |         |         /\                 /\  
    //      |_________|_________|                  |
    //                |____________________________| 
    ComplexListNode* pA = new ComplexListNode();
    pA->m_nValue = 10;

    ComplexListNode* pB = new ComplexListNode();
    pA->m_pNext = pB;
    pB->m_nValue = 20;

    ComplexListNode* pC = new ComplexListNode();
    pB->m_pNext = pC;
    pC->m_nValue = 30;

    ComplexListNode* pD = new ComplexListNode();
    pC->m_pNext = pD;
    pD->m_nValue = 40;

    ComplexListNode* pE = new ComplexListNode();
    pD->m_pNext = pE;
    pE->m_nValue = 50;

    pA->m_pSibling = pC;
    pB->m_pSibling = pE;
    pD->m_pSibling = pB;

    ComplexListNode* pA1 = Clone(pA);
    Clone(NULL);
    Clone(new ComplexListNode());

    system("pause");
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值