单链表中等难度的题目:复制带随机指针的链表(C语言)

题目要求

1.控制随机指针:新的链表节点的random指针指向和原链表相对应新链表的数据。
举个例子:原链表的中间节点的random如果指向原链表的头节点,则新链表的中间节点的random指向新链表的头节点。
2.原链表保持不变
3.原链表和复制链表中的这些指针能够表示相同的链表指向。

解题思路 + 画图分析 + 解题步骤

目标:使用原节点快速找到拷贝节点。 如果实现目标,上面的一切要求都迎刃而解。

解题思路三步走:

第一步

每个原节点,在其后一个位置都拷贝一个,并链接在一起。如下图所示。
第一步的解题思路图

第二步

寻找新节点的random,而新节点的random就是原来random->next。如下图所示
第二步的解题思路图

第三步

把拷贝的节点取出,链接成新的链表,同时恢复原链表。如下图所示:
第三步的解题思路图

题解

对应第一步的代码:拷贝节点

拷贝节点

//首先设立三个指针,分别指向对应图上的位置,前中后
struct Node* cur = head;
while (cur)
{
    struct Node* next = cur->next;
    struct Node* copy = (struct Node*)malloc(sizeof(struct Node));
    if(NULL == copy)
    {
        perror("malloc");
        return NULL;
    }

	//把原节点的数据赋值给拷贝节点的数据域
    copy->val = cur->val;

	//更新指针
    cur->next = copy;
    copy->next = next;
    cur = next; 
}

对应第二步的代码:寻找拷贝节点random的位置

//重置cur
cur = head;

while (cur)
{
	//两个指针cur指向原节点,copy指向该原节点的拷贝节点
    struct Node* copy = cur->next;
    
    //对random指向空进行特殊处理
    if (NULL == cur->random)
    {
        copy->random = NULL;
    }
    else
    {
        copy->random = cur->random->next;
    }
    
    //更新指针
    cur = cur->next->next;
}

对应第三步的代码:拆取拷贝节点,链成新的链表,恢复原链表

//拆取
//重置cur
cur = head;

//定义拷贝链表的头节点和尾节点
struct Node* copyHead = NULL;
struct Node* tail = NULL;
while (cur)
{
	//如第一步定义三个指针,前中后
    struct Node* copy = cur->next;
    struct Node* next = copy->next;

	//首先解决头节点为空的情况
    if (copyHead == NULL)
    {
        copyHead = tail = copy;
    }
    else
    {
    	//尾插
        tail->next = copy;
        tail = tail->next;
    }

    //恢复
    cur->next = next;
    //更新指针
    cur = next;
    
}//End of while

全部代码步骤合在一起

struct Node* copyRandomList(struct Node* head) 
{
	struct Node* cur = head;

    while (cur)
    {
        struct Node* next = cur->next;
        struct Node* copy = (struct Node*)malloc(sizeof(struct Node));
        if(NULL == copy)
        {
            perror("malloc");
            return NULL;
        }

        copy->val = cur->val;
        cur->next = copy;
        copy->next = next;
        cur = next; 
    }

    cur = head;
    while (cur)
    {
        struct Node* copy = cur->next;
        struct Node* next = copy->next;
        
        if (NULL == cur->random)
        {
            copy->random = NULL;
        }
        else
        {
            copy->random = cur->random->next;
        }
        cur = next;
    }

    //拆
    cur = head;
    struct Node* copyHead = NULL;
    struct Node* tail = NULL;
    while (cur)
    {
        struct Node* copy = cur->next;
        struct Node* next = copy->next;

        if (copyHead == NULL)
        {
            copyHead = tail = copy;
        }
        else
        {
            tail->next = copy;
            tail = tail->next;
        }

        //恢复
        cur->next = next;
        cur = next;
    }

    return copyHead;
}

总结

复杂链表的复制这一题,为中等难度。做出这一题代表对单链表有一定理解。
当借鉴的多了,思考的多了,也会形成属于自己的思想。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kpl_20

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值