剑指offer 复杂链表的复制(C++)

本文探讨了复杂链表的复制方法,包括个人思路和官方思路。个人思路通过创建新链表并逐个添加random指针,而官方思路则在原链表中插入复制节点,简化了random指针的复制过程。

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

题目描述

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

解题思路

自己的思路和官方的思路:

自己的思路:

  1. 按照原链表赋值出一份新的链表,但不复制random指针。
  2. 按照原链表遍历的方式,对新链表添加random指针。

官方思路:

  1. 在原链表的基础上,每个结点后面均复制新的结点。
  2. 原链表遍历,同时给复制结点添加random指针。
  3. 原链表与新链表拆分。

代码实现

  1. 自己思路:
    又犯了很低级错误,在牛客网的剑指offer平台上,因为一个英文的逗号写成了中文逗号,检查了很长时间, 下次将for循环中的逗号,改成 && 这样 是可以的。
/*
struct RandomListNode {
    int label;
    struct RandomListNode *next, *random;
    RandomListNode(int x) :
            label(x), next(NULL), random(NULL) {
    }
};
*/
class Solution {
public:
    RandomListNode* Clone(RandomListNode* pHead)
    {
        if(pHead == NULL)
            return NULL;
        
        RandomListNode* pHeadNew = CopyLinkList(pHead);
        
        InsertRandomPointer(pHead, pHeadNew);
        
        return pHeadNew;
    }
    
    RandomListNode* CopyLinkList(RandomListNode* &pHead)
    { // 与头插法混淆 这是复制链表
        if(pHead == NULL)
            return NULL;
        RandomListNode* p = pHead;
        RandomListNode* pHeadNew = NULL; // 新链表的头结点
        RandomListNode* pHeadNewTemp = pHeadNew, *p2 = pHeadNew;
        for(; p; p = p->next)
        {
            pHeadNewTemp = new RandomListNode(p->label);
            if(pHeadNew)
            {
                p2->next = pHeadNewTemp;
                p2 = pHeadNewTemp;
            }
            else
            {
                pHeadNew = pHeadNewTemp;
                p2 = pHeadNewTemp;
            }
        }
        return pHeadNew;
    }
    
    void InsertRandomPointer(RandomListNode* &pHead, RandomListNode* &pHeadNew)
    {
        if(pHead == NULL || pHeadNew == NULL)
            return;
        RandomListNode* pHeadtemp = pHead, *pHeadNewtemp = pHeadNew;
        for(; pHeadtemp, pHeadNewtemp; pHeadtemp = pHeadtemp->next, pHeadNewtemp = pHeadNewtemp->next)
        {
            if(pHeadtemp->random)
            {
                RandomListNode* pHeadSearch = pHead, *pHeadNewSearch = pHeadNew;
                for(; pHeadSearch && pHeadNewSearch; pHeadSearch = pHeadSearch->next, pHeadNewSearch = pHeadNewSearch->next) 
                    //英文逗号 与 中文逗号 太相似
                    if(pHeadSearch == pHeadtemp->random)
                    {
                        pHeadNewtemp->random = pHeadNewSearch;
                        break;
                    }
            }
        }
    }
};
  1. 官方思路解法:
*/
class Solution {
public:
    RandomListNode* Clone(RandomListNode* pHead)
    {
        if(pHead == NULL)
            return NULL;
        NewNodeCopy(pHead);
        
        InsertRandomPointer(pHead);
        
        return GetNewRandomList(pHead);
    }
    void NewNodeCopy(RandomListNode* &pHead)
    {
        if(pHead == NULL)
            return;
        RandomListNode* pTemp = pHead, *pNewNode = NULL;
        while(pTemp)
        {
            pNewNode = new RandomListNode(pTemp->label);
            pNewNode->next = pTemp->next;
            pTemp->next = pNewNode;
            pTemp = pNewNode->next;
        }
    }
    
    void InsertRandomPointer(RandomListNode* &pHead)
    {
        if(pHead == NULL)
            return;
        RandomListNode* pTemp = pHead, *pNewTemp = pHead->next; 
        while(pTemp)
        {
            if(pTemp->random)
                pNewTemp->random = pTemp->random->next;
            pTemp = pNewTemp->next;
            pNewTemp = pTemp->next;
        }
    }

    RandomListNode *GetNewRandomList(RandomListNode *head)
    { 
        RandomListNode *pNode = head;
        RandomListNode *result = head->next;
        while (pNode != NULL)
        {
            RandomListNode *pClone = pNode->next;
            pNode->next = pClone->next;
            pNode = pNode->next;
            if (pNode != NULL)
                pClone->next = pNode->next;

        }
        return result;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值