链表OJ—Leetcode138.随机链表的复制 Leetcode142.环形链表

先说明此题的方法,设置两个指针,一个快指针fast一次走两步,一个慢指针slow一次走一步,若是环形链表,那么相遇的结点则设为meet,那么头结点head和meet结点同时向后走,最后相遇的结点便是入环第一个结点,接下来便让我逐步分析如何得出的结论

首先让我们分析一下题目的意思,此题要求不是环形链表则直接返回NULL,若为环形链表则返回进入环的第一个结点

所以我们的第一步则是应该首先判断是否为环形链表,那么如何去判断呢?其实这个问题并不难,只要我们判断指针是否能走到末尾便可以,此处我们只需要一个while循环便可以解决

    while(fast&&fast->next)
    {  
        fast=fast->next->next;
        slow=slow->next;
        if(fast==slow)  //若fast与slow相遇则链表带环
        {
            struct ListNode *meet=fast;
            
        }
    }
    return NULL;   //若走出while循环则表明链表不带环
           

那么第二步则是我开头所说的方法了,完整代码如下

struct ListNode *detectCycle(struct ListNode *head) {
    struct ListNode *fast=head,*slow=head;
    while(fast&&fast->next)
    {  
        fast=fast->next->next;
        slow=slow->next;
        if(fast==slow)
        {
            struct ListNode *meet=fast;
            while(head!=meet)
            {
                head=head->next;
                meet=meet->next;
            }
            return meet;
        }
    }
    return NULL;
}

那么最重要的来了,这个方法是如何得出来的呢?接下来便让下面图片来解释

那么最终我们会发现相遇后meet所走的距离是圆周长度的倍数加上长度c-n,而c-n恰好就是meet距离入环处的距离,所以最后会相遇在入环处,是不是很巧妙?

那么接下来这题复制链表通过了解题目,通俗的来说就是将原链表拷贝一份一样的进行输出,老样子,先说明此题的解题思路,首先将链表遍历一遍,每个原结点复制出一个一样的新结点并填入对应val,并将原结点与复制结点连接起来,找到对应的random,最后将原链表与复制的分离,最重要的便是如何去找random,那么听我接下来的分析

第一步,复制结点并连接,代码如下

   struct Node* cur=head;
    while(cur)
    {
        struct Node* next=cur->next;
        struct Node* copynode=(struct Node*)malloc(sizeof(struct Node));
        copynode->val=cur->val;
        cur->next=copynode;
        copynode->next=next;
        cur=next;
    }

第二步,找到random,原结点的random指向的结点的next结点就是复制结点random指向的结点,为什么呢?原因其实也很简单,复制的每个结点都是连接在原结点后面,那么自然原结点的random指向的结点的next结点就是复制结点random指向的结点,下面一张图带你加深一下理解

图有点抽象,简单解释一下就是11结点的random指向1,1的next指向复制结点的1,这样复制结点的11的random不就找到了吗,废话不多说第二步代码如下

    cur=head;  //用之前cur记得回复一下哦
    while(cur)
    {
        struct Node* copycur=cur->next;
        struct Node* next=copycur->next;
        if(cur->random==NULL)
        {
            copycur->random=NULL;
        }
        else
        {
            copycur->random=cur->random->next;
        }
        cur=next;
    }

第三步就是最简单的啦,将复制的结点串到一起,这里我使用的是带头结点的尾插法,代码如下

    cur=head;  //老样子不要忘了把cur恢复哦
    struct Node* phead=(struct Node*)malloc(sizeof(struct Node));
    phead->next=NULL;
    struct Node* copytail=phead;
    while(cur)
    {
        struct Node* copycur=cur->next;
        struct Node* next=copycur->next;
        copytail->next=copycur;
        copytail=copytail->next;
        cur=next;
    }
    return phead->next;

完整代码如下

struct Node* copyRandomList(struct Node* head) {
	struct Node* cur=head;
    while(cur)
    {
        struct Node* next=cur->next;
        struct Node* copynode=(struct Node*)malloc(sizeof(struct Node));
        copynode->val=cur->val;
        cur->next=copynode;
        copynode->next=next;
        cur=next;
    }
    cur=head;
    while(cur)
    {
        struct Node* copycur=cur->next;
        struct Node* next=copycur->next;
        if(cur->random==NULL)
        {
            copycur->random=NULL;
        }
        else
        {
            copycur->random=cur->random->next;
        }
        cur=next;
    }
    cur=head;
    struct Node* phead=(struct Node*)malloc(sizeof(struct Node));
    phead->next=NULL;
    struct Node* copytail=phead;
    while(cur)
    {
        struct Node* copycur=cur->next;
        struct Node* next=copycur->next;
        copytail->next=copycur;
        copytail=copytail->next;
        cur=next;
    }
    return phead->next;
}

可能写的不是很好,请大家多多包含,谢谢!

  • 17
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值