经典的带环链表问题(链表补充)

简介: 经典的带环链表问题(链表补充)

环形链表1

运用快慢指针的方法,fast ,slow从头节点出发,快指针走两步,慢指针走一步,若有环,快指针先进环,后续如果慢指针和快指针相遇,则链表带环。转换成了追击问题。


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

思考:为什么一定会相遇,会不会错过,永远追不上?若快指针走三步,四步呢?

证明:假设链表就是有环,slow(1步)进环时,fast(两步)与slow的距离为N,追击过程中,每走一次,N都会-1,最后到0。本题的思想证明,距离为0就是追上了。

若fast走三步,同样假设slow进环时,fast与slow相差N,

fast追击slow过程中,距离变化一直-2,但是最后结果要注意,N为偶数时,最后变为0,N为奇数时,最后为-1.而当距离为-1时,两指针会错过,进行新一轮追击。这时假设环的长度为C。新的距离就变成C-1了,这是又要将C分为奇数,偶数进行讨论。

那么是否存在N是奇数且C是偶数的情况呢,

假设从出发位置到进环的位置相差L,slow进环时,fast已经走了x圈,且fast与slow相差N:

进环时:slow走的距离->L

fast走的距离->L+x*C+C-N

fast的距离应该为slow的三倍:3*L=L+x*C+C-N

化简为:2*L=(x+1)*C-N  若要满足该等式,若C是偶数,N必须是偶数。若N是奇数,如果C是偶数,则(x+1)*偶数一定是偶数,偶数-奇数!=偶数。

所以上述条件不成立,故永远追不上的条件不成立。

结论:一定能追上。

N是偶数第一轮追上。N是奇数第一轮追不上,C是奇数,第二轮追上。

其他走四步等的条件证明过程类似。

环形链表2

本题相较于第一个环形链表题,多了返回节点位置的步骤,所以最初思路也是通过快慢指针,快慢指针相遇,则证明有环存在,然后将两指针相遇点记为meet,再继续走,此时头节点也开始移动,meet与head相遇点就是环的最初节点。

证明过程如下:

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

这种方法不容易想到,还有另外一种方法,将快慢指针相遇点newhead=meet->next,meet->next=NULL,此时从newhead开始,与原链表head通过相交链表的思路求解。


struct ListNode {
    int val;
   struct ListNode *next;
 };
 
 typedef struct  ListNode LN;
 struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    LN*cur1=headA,*cur2=headB;
    int lenA=1,lenB=1;
    while(cur1){
        cur1=cur1->next;
        lenA++;
    }
    while(cur2){
        cur2=cur2->next;
        lenB++;
    }
    //尾节点不相同就没有相交
    if(cur1!=cur2){
    return NULL;
    }
    //假设法
    int gap=abs(lenA-lenB);
    LN* longlist = headA;
    LN* shortlist = headB;
    if(lenA<lenB){
        longlist=headB;
        shortlist=headA;
    }
    while(gap--){
     longlist=longlist->next;
    }
    while(longlist!=shortlist){
        longlist=longlist->next;
        shortlist=shortlist->next;
    }
    return longlist; 
}
struct ListNode *detectCycle(struct ListNode *head) {
    LN*slow,*fast,*meet;
    slow=fast=head;
    while(fast && fast->next){
        slow=slow->next;
        fast=fast->next->next;
        if(slow==fast){
        meet=slow;
        LN* newhead=meet->next;
        meet->next=NULL;
        return getIntersectionNode(head,newhead);  
        }                
}
return NULL;
   
}

本节内容到此结束,感谢各位友友对小编的支持!!!

觉得本文章有用的话留下三连和评论吧!!!

咱们下期再见!!!

目录
相关文章
数据结构:链表的一些经典的OJ题目,环形链表问题
数据结构:链表的一些经典的OJ题目,环形链表问题
代码随想录Day03 | 链表基础1 LeetCode T203 移除链表元素 T707设计链表 T206 反转链表
代码随想录Day03 | 链表基础1 LeetCode T203 移除链表元素 T707设计链表 T206 反转链表
55 0
|
6月前
|
存储 算法 C语言
【链表专题】深入探索链表:文章索引与知识架构(链表的概念、实现、应用、经典例题大合集)
【链表专题】深入探索链表:文章索引与知识架构(链表的概念、实现、应用、经典例题大合集)
|
7月前
<数据结构>五道LeetCode链表题分析.环形链表,反转链表,合并链表,找中间节点.
<数据结构>五道LeetCode链表题分析.环形链表,反转链表,合并链表,找中间节点
60 1
|
6月前
|
存储 算法
数据结构和算法学习记录——线性表之单链表(上)-初始单链表及其尾插函数(顺序表缺陷、单链表优点、链表打印)
数据结构和算法学习记录——线性表之单链表(上)-初始单链表及其尾插函数(顺序表缺陷、单链表优点、链表打印)
44 0
LeetCode刷题Day04——链表(设计单/双链表、移除、翻转、交换链表节点)
迭代法:首先创建一个临时的节点p用于遍历链表,其开始可以指向头节点,也可以让其next节点指向头节点(如果p指向头节点则while循环的判断条件是p!=null,反之则是p.next!=null),随后p不断地向后移动,在这个过程中进行要求的操作。如果结果要返回头指针,可以实现创建一个节点让其next指向头指针。 如果是要删除元素,那么需要拥有前一个节点的指针,让其指向要删除的元素的下一个元素,所以此时则不能让p指向头节点,而应该是让next去指向,即判断的是下一个元素的值,这样才能够实现删除。 如果是要翻转链表,那么需要不断改变指针的方向,即让next等于之前的元素,所以需要一个变量prev
|
算法
代码随想录算法训练营第四天 | LeetCode 24. 两两交换链表中的节点、19.删除链表的倒数第N个节点、面试题 02.07. 链表相交、142.环形链表II
代码随想录算法训练营第四天 | LeetCode 24. 两两交换链表中的节点、19.删除链表的倒数第N个节点、面试题 02.07. 链表相交、142.环形链表II
163 0
|
存储 算法
代码随想录算法训练营第四天 | 24. 两两交换链表中的节点 ,19.删除链表的倒数第N个节点 ,面试题 02.07. 链表相交 ,142.环形链表II
代码随想录算法训练营第四天 | 24. 两两交换链表中的节点 ,19.删除链表的倒数第N个节点 ,面试题 02.07. 链表相交 ,142.环形链表II
代码随想录Day4 链表基础2 LeetCodeT24 两两交换链表中的节点 LeetCode T19删除链表的倒数第N个节点 LeetCode面试题 链表相交 LeetCode 142 环形链表
代码随想录Day4 链表基础2 LeetCodeT24 两两交换链表中的节点 LeetCode T19删除链表的倒数第N个节点 LeetCode面试题 链表相交 LeetCode 142 环形链表
28 0