每日一题(复制带随机指针的链表)

每日一题(复制带随机指针的链表)

138. 复制带随机指针的链表 - 力扣(LeetCode)

每日一题(复制带随机指针的链表)_第1张图片

思路:

由于每个链表还包含了一个random节点指向了链表中的随机节点,所以并不能直接照搬复制原链表。首先想到的暴力思路是复制一条新的链表。找到原链表的每个节点的random到该节点的相对举例。但是实际上操作起来更复杂。

这里提供另外一个思路:

  • 第一步:创建新节点

在原链表的每个节点之后紧跟着复制一个节点,形成新老节点相间的局面,并且将原链表的每个节点的值赋值给其后创建的节点中,并且将新开辟的节点的random成员的值设置为NULL,如下图:

每日一题(复制带随机指针的链表)_第2张图片

  • 第二步:设置新节点random的值

创建一个cur指针指向原链表的第一个节点,再创建一个newhead指针指向cur的next;cur指针从head处出发,newhead从head->next处出发。开始遍历链表。这里有一个最重要的关系:当cur->random不为空时,(当cur->random的值为NULL时,则不做改动)满足:cur->random与cur的对应关系与newhead->random和cur->random->next的对应关系时一样的。

就可以根据这些对应关系修改新创建的节点的random的值。接着cur向后移动两步指向下一个原链表中的节点,newhead也向后走两步指向下一个新开辟的节点。如下图所示(红色的是random指针,绿色的是next指针):新节点之间的random的链接关系和原链表的random的链接关系并没有改变。
每日一题(复制带随机指针的链表)_第3张图片

  • 第三步:断开链表

创建三个指针cur1和cur2和newhead,cur1从head的next处开始遍历,cur2从head处开始遍历,newhead指针用于记录cur1的起始位置。将原链表的节点和新链表的节点各自分成一条链表。特别注意:这里的遍历迭代的顺序不得交换! 在两个指针向后更新的过程中,肯定是cur1->next先为NULL,当cur1->next为NULL时就退出循环,但是此时的cur2的next指针仍然指向的是新开辟的最后一个节点。所以在返回newhead之前,要将cur2->next置为NULL。
每日一题(复制带随机指针的链表)_第4张图片

代码实现:

	if(head==NULL)
    {
        return NULL;
    }
    struct Node* cur = head;
    struct Node* curNext = head;
    struct Node* newhead = head;

    //构造相间的节点
    while(cur!=NULL)
    {
        curNext = cur->next;
        struct Node* newnode = (struct Node*)malloc(sizeof(struct Node));
        if(newnode== NULL)
         return NULL;
        newnode->val = cur->val;
        newnode->random =NULL;
        //新节点链接在原节点之后
        cur->next = newnode;
        newnode->next = curNext;
        cur = curNext;
    }


    cur = head;
    //复制各自的random
    while(cur!=NULL)
    {
        newhead = cur->next;
        if(cur->random!=NULL)
        {
            newhead->random = cur->random->next;
        }
        cur = cur->next->next;
    }

    //断开
    newhead = head->next;
    struct Node* cur1 = newhead;//cur1用于遍历newnode
    struct Node* cur2 = head;//cur2用于遍历原链表的节点
    while(cur1->next)
    {
        cur2->next = cur2->next->next;
        cur1->next = cur1->next->next;
        cur2 = cur2->next;       
        cur1 = cur1->next;

    }
	//将cur2->next置空
    cur2->next = NULL;
    return newhead;

完结

复制带随机指针的链表习题的分析就到这里啦,若有不足,欢迎评论区指正,下期见!

你可能感兴趣的:(数据结构与算法,链表,数据结构,算法,c语言)