力扣---复制带随机指针的链表

目录


1.题目解析

2.解题思路

3.思路转换为代码

4.源码


1.题目解析


题目连接:力扣

 首先要理解题目的原意,才能正确理解这道题目的解法:

题目的大概意思就叫我们复制一份题目中的链表,并返回新链表的头

这题看似只是复制,但是这题目并不简单

新链表指针也应该指向新节点

那么next指针很容易做得到的,但是random是比较难,因为random指针不是单纯的指向下一个节点,而是没有顺序的

它可能指向自己,可以可能指向空,也可能两个指针同时指向一个节点

那么遍历去拷贝到新链表,明显是行不通的

那这题我们该怎么解题呢?


2.解题思路


解题总共需要三步

第一步:

我们在每个节点后面申请新的节点

并且新的节点是前一个节点的值的拷贝

 

 总结来说 copy就是cur的一份拷贝,只不过curnextrandom指针没有拷贝过去

并且让他们连接起来

他们其实就是一个链表,copy之所以在上面,我是想让读者知道他们是插入的新节点


第二步:

接下来把新节点copy的random指针指向 cur的random指向的地方,就是把cur的random拷贝到copy里。

相当于copy就是cur的值和random的指针的一份拷贝

然后用循环去解决

这样是不是可以看出 我们就拷贝了cur (只不过cur的next不拷贝过去)

 这样我们就拷贝了一遍原链表


第三部:

把已经拷贝好的节点,连接到一起

我们一样 创建新链表的头和尾,然后把这些节点依次拷贝到新链表里面。

最后我们返回新链表的头。

这道题我们就解决了


3.思路转换为代码


第一步:


要在链表的每个节点后面新创建一个节点,当然需要malloc来申请

这里可以有两种写法(效果都一样)


第一种:

我们创建两个指针,一个指向头,一个指向头的下一个节点

然后利用这两个节点,在这两个节点中插入一个新节点

然后让这两个指针同时向后移动,保持他们是一个在前,一个在后的状态

 逻辑图如上

代码如下

	struct Node* cur=head;
    while(cur)//分别在每个节点的后面创建一个新节点
    {
        struct Node* copy=(struct Node*)malloc(sizeof(struct Node));
        struct Node* end=cur->next;
        
        copy->next=end;
        cur->next=copy;
        copy->val=cur->val;

        cur=end;
    }

第二种:

我们只创建一个指针。

插入新节点时,需要注意顺序,一定要让新节点先指向后一个节点,在让前一个节点指向新节点,这里有点绕,我放图会跟清晰

 如果你先执行2时 那么cur->next已经改变,指向了新节点,那么唯一能找到第二个节点的指针就被该了,那么copy就找不到下一个节点。

所以我跟推荐用第一种,第一种的顺序不必要这么准确


第二步:


因为刚才cur通过循环已经走到NULL了

1.这一次我们要让它从头开始遍历,所以我们要让cur重置为head

2.然后我要找到copy的位置,copy都是cur的拷贝,当然就是在cur->next

4.前面说了,cur->random可能为空,所以我们对这个情况要单独判断下

5.因为我们要让新节点连接 所以random一定要指向新节点 (cur->random->next)

6.最后让cur移动 移动到下一个的下一个节点(注意,要移动到旧节点。而不是新节点)


第三步:


接下来我们就要把新节点全部连接到新的链表里

1.先创建新链表的头和尾,cur要重新遍历,所以cur要重置为head

然后我们再创建两个指针

一个是指向copy(copy)一个是指向copy的下一个节点(end)

2.让cur重新指向旧节点,让他们还原,不在指向新节点

3.第一次进入时,头和尾为空,所以我们要单独处理这个情况

4.其余条件我们正常接入节点

5.让cur移动到end的位置(相当于移动)

6.最后我们返回新链表的头


4.源码


struct Node* copyRandomList(struct Node* head) {
	struct Node* cur=head;
    while(cur)//分别在每个节点的后面创建一个新节点
    {
        struct Node* copy=(struct Node*)malloc(sizeof(struct Node));
        struct Node* end=cur->next;
        
        copy->next=end;
        cur->next=copy;
        copy->val=cur->val;

        cur=end;
    }

    cur=head;
    while(cur)
    {                  //把copy(新节点)的random指向cur->random的后一个节点
        struct Node* copy=cur->next;//这个后一个节点正是cur的值

        if(cur->random==NULL)
        {
            copy->random=NULL;
        }
        else
        {
            copy->random=cur->random->next;
        }
        cur=cur->next->next;
    }

    struct Node* Headhead=NULL,*Tailhead=NULL;
    cur=head;

    while(cur)
    {            //把copy全部链接到新的链表里
        struct Node* copy=cur->next;
        struct Node* end=copy->next;
        cur->next=end;

        if(Tailhead==NULL)
        {
            Tailhead=Headhead=copy;
        }
        else
        {
            Tailhead->next=copy;
            Tailhead=Tailhead->next;
        }
        
        cur=end;
    }
    return Headhead;
}

如果本章对你有帮助,希望能获得你的赞~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值