Leetcode--复杂链表的复制

题目描述:

请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。

在这里插入图片描述
在这里插入图片描述

分析1:

我们可以依次遍历这个链表,用一个哈希结构<Node*,Node*>来存储每个节点与新构建的节点的关系,这样一来,新节点的的指针域就可以从键域的指针域来获得。
如:1->2->3, 哈希结构为(1,1) (2,2) (3,3),
Node* tmp = head;
mmap[tmp]->next=mmap[tmp->next];
mmap[tmp]->random = mmap[tmp->random];

代码1:

 	unordered_map<Node*,Node*> mmap;
    Node* copy(Node* head)
    {
        for(Node *tmp = head;tmp != NULL;tmp = tmp->next)
        {
            mmap[tmp] = new Node(tmp->val); //构建新的节点
        }
        for(Node *tmp = head;tmp != NULL;tmp = tmp->next)
        {
            mmap[tmp]->next = mmap[tmp->next];//新的节点的指针域根据键域来获得
            mmap[tmp]->random = mmap[tmp->random];
        }
        return mmap[head];
    }
    Node* copyRandomList(Node* head)
    {
        if(head == NULL) return NULL;
        return copy(head);
    }

分析2:

如果用哈希表来存储节点与新节点的关系,空间复杂度就为O(n),如果我们原地构建链表即不使用额外空间,我们可以在遍历链表的过程中,在每个节点的后面创建一个新的节点,然后ptr=ptr->next->next来遍历原链表,在建立完之后我们再从头到尾遍历一次旧节点,新节点的指针域根据对应的旧节点的指针域来获得,最后分开旧链表与新链表

  1. 遍历旧链表,并在每个节点后面创建一个新的节点
  2. 构建新节点的random指针域
  3. 分开旧链表与新链表----完成新节点的next域的构建

代码2:

 Node* copy(Node* head)
    {
        /在原链表基础下拷贝
        Node* cur = head;
        while(cur != NULL)
        {
            Node* copyNode = new Node(cur->val);
            copyNode->next = cur->next;
            cur->next = copyNode;
            cur = cur->next->next;
        }

        /将拷贝出来的random进行指向
        cur = head;
        while(cur != NULL)
        {
            if(cur->random != NULL)
            {
                cur->next->random = cur->random->next;
            }
            cur = cur->next->next;
        }

        /分离原链表与拷贝出来的链表
        Node* copyhead = head->next;
        cur = head;
        Node* curcopy = head->next;
        while(cur != NULL)
        {
            cur->next = cur->next->next;
            cur = cur->next;
            if(curcopy->next != NULL) //如果不是最后一个
            {
                curcopy->next = curcopy->next->next;
                curcopy = curcopy->next;
            }
        }
        return copyhead;

    }
    Node* copyRandomList(Node* head)
    {
        if(head == NULL) return NULL;
        return copy(head);
    }

注意事项:

我们不能使新节点的next指针与random指针指向旧链表中的节点!
下面是错误的做法

  unordered_map<Node*,Node*> mmap; //记录节点与节点随机指针的映射关系

    Node* copy(Node *head)
    {
        Node* ptr = head;
        Node* newptr = new Node(0);
        Node* pp = newptr;
        while( ptr != NULL )
        {
            mmap[pp] = ptr->random;  //在这里新节点的random指向的是旧链表中的节点,
            								并没有构造出新的节点

            pp = pp->next;
            ptr = ptr->next;
        }

        Node* ppp = newptr;
        while(ppp != NULL)
        {
            ppp->random = mmap[ppp];
            ppp = ppp->next;
        }
        return newptr;
    }


    Node* copyRandomList(Node* head)
    {
        if(head == NULL) return NULL;
        return copy(head);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值