[C语言]初阶数据结构---链表习题

经典问题---链表带环问题

最后一个节点的next指针,本来应该指向空指针,但是现在指向前面的节点(非NULL),这样就构成了带环链表

例子1:

判断链表是否带环(力扣)

解题代码如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
bool hasCycle(struct ListNode *head) {
    struct ListNode*slow=head,*fast=head;
    while(fast&&fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
        if(fast==slow)
        {
            return true;
        }
    }
    return false;
}

如果fast指针为NULL或者fast->next指针为NULL,就跳出循环,返回false。

毫无疑问,这道题的思路和代码都是非常简单的。

但是当我们思考得深一点时,slow进入环时,slow和fast指向同一个节点时返回true,那问题来了,两个指针一定会相遇吗?会不会错过呢?

2.原题是slow一次走一步,fast一次走两步。

如果fast一次走3步,4步,5步......N步呢?

所以就画图接着分析当N为奇数的情况

当值为-1时,说明fast已经超过了slow指针一步,设带环部分长为C,按fast追击slow的角度,则此时两指针相差C-1个距离。

这样就有回到了开始时的状态,不过起始距离不是N,而是C-1。

总结一下:(不一定对)

1.N为偶数,第一轮追击就会相遇。

2.N为奇数:第一轮追击错过,距离变为C-1。

   a.C-1为偶数,第二轮就相遇。

   b.C-1为奇数,这一轮最后距离还是C-1,进入循环,不会相遇。

那就需要一个等量关系来表示两者的关系了。还记得吗,fast的指针速度是slow的3倍,所以fast

走的距离也是slow的3倍。

当slow刚进入链表带环部分时,

slow=L

fast=L+X*C+C-N      ,X为整数,X*C表示fast绕带环部分几圈了,最后多走C-N的距离。

3slow=fast

最后化简2L=(X+1)*C-N,对这个表达式简单的分析,等式的左边一定为偶数,N为奇数进入第二轮循环,按上面的分析C为偶数时就不会相遇,但是当C为偶数时,等式左边这个整体还为偶数吗?

显然一个偶数减去一个奇数为奇数,而2L为偶数,所以不存在C为偶数,同时N为奇数这种情况,即两快慢指针一定会相遇

例子2:

随机链表的深拷贝(来自力扣)

ps:深拷贝的意思就是拷贝这个链表,链表中一个节点的val值,next指针的指向,随机指针的指向,都与原来给定的链表的内容完全相同,但是链表每个节点的地址与原来对应链表的节点的地址不同。(题中这么长的信息的意思就是这个意思)

首先思考,

1.用malloc函数开辟节点,然后赋值原链表的val值,next指针指向下一个新创建的节点。

如图:

或许普通单链表可以这样,但是这里面的random指针,你如何去找呢?

所以像这种直接malloc然后用next指针串起来是不行的,random指针的指向只有在原链表中才可以体现出来,所以应该思考如何将开辟的新节点与原链表扯上关系,既然不能直接将拷贝后的链表单独拿回来,那就将拷贝后的放到原链表去找两个链表之间的关系。

如图:将malloc后的节点插入到原节点的后面

这样就建立起了拷贝节点之间random指针之间的关系,最后再将链表恢复(将拷贝链表分离出来)

总结:

链表题要多多画图,多多分析,才能进步!!!

  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值