环形链表的学习

大家好,今天我对环形链表进行了一个学习,下面是我的学习内容

1.给定一个链表,判断链表中是否有环。141. 环形链表 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/linked-list-cycle/description/

对于这一题 首先我们要明白 如果成环 代表着链表是循环的 如图

可以把他的循环想象成走了一段距离 然后 形成一个圆的循环

对此 我的思路是快慢指针  快的指针走 慢的指针在快的指针走了一遍或者x遍循环之后

如果两个指针相遇  也就意味着循环成环

下面是解题过程

为什么一定会相遇呢?我认为一定会相遇 证明  

在快慢指针的过程中 我们需要判断快的指针要走多少步

如果快指针一次走两步的话 假设slow进环时 与fast的距离为N(偶数) 接着每进行下一次行动 距离变成N-1 N-2……2 1 相遇。

如果走三步呢 假设slow进环时 与fast的距离为N(奇数) 接着每进行下一次行动 距离变成N-2 N-4 ……3 1 -1 这时候就要分情况总结了

距离为-1的话  进行下一次环的循环 此时环的距离为C-1

分两种情况C-1为偶数  C-1为奇数

偶数的循环因为fast每次和slow相差的距离为2 后面的距离 4 2 0相遇;为奇数 继续开启下一次的追击 C-2 …… 

因此 总结一下  如果 N为偶数的话 第一次循环就相遇 如果 N为奇数的话 第一轮的追击错过 

开启新的一轮(C-1),如果C-1为偶 相遇 C-1 为奇数 继续追击…… 

fast走4 5 ……情况类似

所以 如果N为奇数C为偶数的话 相遇不到一起  

如果用公式来计算的话

假设fast走3步  slow进环时 fast已经走了x圈  slow走了L距离  fast走了L+C*x+C-N

3L = L+C*x + C -N;

2L = (x+1)C -N;

偶数 =(x+1)偶数 -奇数

显然不相等

反正N为奇数且C为偶数条件不能同时存在  ,永远追不上的条件不成立

结论:一定能追上

追上的话就是1.N为奇数   第一轮追击C-1

                         a.C-1为偶数的话 追上

                         b.C-1为奇数的话 永远追不上 

                      2.N为偶数 C为偶数

                        第一轮就追上

下面是代码

bool hasCycle(struct ListNode *head) {
    struct ListNode* slow = head,*fast = head;
    while(fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
        if(slow == fast)
        return true;
    }
    return false;
}

2.环形链表IIhttps://leetcode.cn/problems/linked-list-cycle-ii/description/ 

返回到成环的入口点

也是快慢指针的方法

下面是我的思考过程

要算出成环的节点  首先判断走的路程

fast 走的是slow的2倍

2(L+N)= x*C + L + N

L+N = x*C

L = x*C -N

所以slow走的路程就是相遇后 从相遇点走到起始成环的地点

代码如下

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

换一种方法

新建一个指针链表

快指针先走 判断插值

在同时走 第一个相等是就是交点  最后返回值就是起始点(这里用到了相交链表的内容)https://leetcode.cn/problems/intersection-of-two-linked-lists/description/

 struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    struct ListNode* newA = headA,*newB = headB;
    int lenA = 0,lenB = 0;
    while(newA)
    {
        newA = newA->next;
        ++lenA;
    }
    while(newB)
    {
        newB = newB->next;
        ++lenB;
    }
    
    //尾节点不相等就是不相交
    if(newA != newB)
    return NULL;

    //长的先走差值  再同时走 第一个相等的就是交点;
    int gap = abs(lenA-lenB);
    struct ListNode* longList = headA,* shortList = headB;
    if(lenB > lenA)
    {
        longList = headB;
        shortList = headA;
    }

    while(gap--)
    {
        longList = longList->next;
    }
    while(longList !=shortList)
    {
        longList = longList->next;
        shortList = shortList->next;
    }
    return shortList;
}

struct ListNode *detectCycle(struct ListNode *head) {
    struct ListNode* slow = head,*fast = head;
    while(fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
        //相遇
        if(slow == fast)
        {
            struct ListNode *meet = slow;
            struct ListNode *newhead = meet->next;
            meet->next = NULL;
            return getIntersectionNode(head,newhead);
        }
    }
    return NULL;
}

今天的内容就结束了

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Leeltc

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

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

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

打赏作者

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

抵扣说明:

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

余额充值