剑指offer:输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。

题目:输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)

分析:

分为三步走:(1)给原来的链表的每个结点复制一个新节点并且插入到对应的后面 (2)利用老节点将新节点的random指针域置好 (3)将链表还原,即拆成完整的两个链表
 

RandomListNode* Clone(RandomListNode* pHead)
    {
        if(pHead==nullptr)
            return nullptr;
        
        //第一步:复制链表结点
        RandomListNode* oldnode=pHead;
        while(oldnode)
        {
            RandomListNode* newnode = new RandomListNode(oldnode->label);//用老节点的值申请一个新节点
            newnode->next=oldnode->next;//将新节点的next链上老节点的next
            oldnode->next=newnode;//将新节点插在老节点后面
            oldnode=oldnode->next->next;//由于已经插入了新节点,因此遍历下一个老节点得走2个next
        }
        
        //第二步:置信结点的random指针
        oldnode=pHead;//oldnode指向链表的开始
        while(oldnode)
        {
            RandomListNode* newnode=oldnode->next;//由于上面的复制,新节点紧跟在与其对应的老节点后面
            if(oldnode->random!=nullptr)
            {
                //oldnode->random是老节点的random域,再指向next就是该老节点对应的新节点应该指向的对应的random域
                newnode->random=oldnode->random->next;
            }
            oldnode=oldnode->next->next;//只走老节点(为其对应的新节点链上对应的randoum域)
        }
        
        //拆分新/老链表
        oldnode=pHead;//让oldnode指向链表开始
        RandomListNode* newHead=oldnode->next;//新链表的头是老链表头的下一个(之前复制了的)
        
        while(oldnode)
        {
            RandomListNode* newnode=oldnode->next;//保证newnode一直紧跟咋oldnode后面(老、新节点相对位置)
            oldnode->next=newnode->next;//恢复老节点的next指向
            
            if(oldnode->next!=nullptr)
            {
                newnode->next=oldnode->next->next;//恢复新节点的next指向
            }
            oldnode=oldnode->next;//由于oldnode的next域上面已经恢复了,因此下一个老节点就是oldnode->next
        }
      return newHead;
    }

猜你喜欢

转载自blog.csdn.net/zy20150613/article/details/90076803
今日推荐