C语言/数据解构——每日一题(随即链表的复制)

目录

一.前言

二.正文

1.1题目描述

1.2题目分析

(i)创建节点,并尾插到原节点后

(ii)将复制节点的random指针指向正确位置

​编辑(iii)将复制链表从原链表上剥离下来

1.3代码实现

三.前言


一.前言

嗨嗨嗨,大家好久不见。已经有好几天没更新了。今天我们就分享一道链表题吧——随即链表的复制https://leetcode.cn/problems/copy-list-with-random-pointer废话不多说,让我们直接开始今天的题目分享吧。

二.正文

1.1题目描述

他和单链表不同的是,结构体里还多一个random指针,指向随机节点。

这道题的意思就是想让我们将原链表完全复制下来,并且将复制好的链表返回到服务器上。

1.2题目分析

(i)创建节点,并尾插到原节点后

这道题我们可以通过遍历一个节点的同时,就穿插一个复制该节点数据的复制节点在该节点后面。

通过循环语句,我们最后会得到一个每一个原节点的后面尾插了一个新的复制节点。如图所示:

这里我们只是先处理了next指针,下面我们将处理random指针。让复制节点的random指针指向和原节点保持一致。

值得注意的是上面的这些节点是我们通过malloc函数自己手动创建的。红叉的地方意味着原来的next指向断掉了。

(ii)将复制节点的random指针指向正确位置

这里我们需要让复制节点的random指针和原节点指向一致,但不是指向原节点,而是指向复制节点。

如果原节点的random指针指向为NULL,那么与之对应的,该节点的复制节点也需要指向NULL。

如果该节点(假设l1)的random指针不指向NULL。而是指向另外一个节点(假设为l2)。那么与之对应的,l1的复制节点的random也应该指向l2的复制节点。那么这一步该如何实现呢?

我们假设一个指针pcur现在指向第三个节点13。pcur->next->random=pcur->random->next。

这样两个复制节点就可以通过pcur建立联系了。如图所示:

(iii)将复制链表从原链表上剥离下来

这里我们可以创建一个哨兵位,然后陆续从后面插入我们需要的复制节点即可。然后将哨兵位后面的有效节点存起来,在哨兵位free掉,归还给操作系统,将指向该哨兵位节点的指针置为NULL。最后返回之前存的有效节点即可

1.3代码实现

**
 * Definition for a Node.
 * struct Node {
 *     int val;
 *     struct Node *next;
 *     struct Node *random;
 * };
 */
typedef struct Node ListNode;
struct Node* copyRandomList(struct Node* head)
{
    if(head==NULL)
    return head;
	ListNode* pcur = head;
	while (pcur)
	{
		ListNode* copy = (ListNode*)malloc(sizeof(ListNode));
		copy->val = pcur->val;
		copy->next = pcur->next;
		pcur->next = copy;
		pcur = pcur->next->next;
	}
	pcur = head;
	while (pcur)
	{
		ListNode* copy = pcur->next;
		if (pcur->random == NULL)
			copy->random= NULL;
		else
			pcur->next->random = pcur->random->next;
		pcur = copy->next;
	}
	ListNode* newhead = (ListNode*)malloc(sizeof(ListNode));
	ListNode* ppcur;
	ppcur = newhead;
	pcur = head->next;
	int count = 0;
	while (pcur)
	{
		if (count % 2 == 0)
		{
			ppcur->next = pcur;
			ppcur = ppcur->next;
		}
		pcur = pcur->next;
		count++;
	}
	ListNode* ret = newhead->next;
	free(newhead);
	newhead = NULL;
	return ret;
}

值得注意的是上面的代码是在力扣环境上运行的。

三.前言

今天的分享就到此结束喽,咱们下次再见,拜拜。

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值