链表--如何检测一个链表是否有环及如何找到环的入口点

如何检测一个链表是否有环
 

有环的链表:

有环的链表是指链表有环路,例如A->B->C->D->E->F->B,遍历的时候B->C->D->E->F->B会形成环路一直循环。

思路: 
设置一个快指针fast,一个慢指针slow,二者初始都指向链表头,fast一次走两步,slow一次走一步,两个指针同时向前移动,每移动一次,两个指针都要进行比较,如果快指针等于慢指针,则证明这是个有环的单链表,否则如果fast先行到达链表尾部或为NULL,则证明这是个不带环的单链表。

代码实现:

public static boolean isLoop(Node head) {
        boolean flag = false;
        Node slow = head;
        Node fast = head;
        while(fast != null && fast.next !=null) {
            fast = fast.next.next;
            slow = slow.next;
            if(fast == slow) {
                flag = true;
                break;
            }
        }
        if(fast == null || fast.next ==null) {
            flag = false;
        }
        return flag;
    } 


如何找到环的入口点


思路: 
如果单链表有环,当slow指针和fast指针相遇时,slow指针还没有遍历完链表,而fast指针已经在环内循环n(n>=1)圈了,假设此时slow指针走了s步,fast指针走了2s步,r为fast在环内转了一圈的步数,a为从链表头到入口点的步数,b为从入口点到相遇点的步数,c为从相遇点再走c步到达入口点,L为整个链表的长度。

slow指针走的步数:
         s = a + b
fast指针走的步数:
        2s = s + n*r 即:s = n*r
链表的长度:
        L = a + b + c = a+r
由上可得:
        2*(a + b) =s +  n*r ​​​​​​
而 b= r - c,所以:
        a + b = n*r 
        a = n *r - b = n*r - (r - c) = (n-1)*r - c
由上可得,所以:
        a = (n -1)*r +c
综上可得:从链表头到环入口点等于(n - 1)循环内环 + 相遇点到环入口点,于是在链表头和相遇点分别设置一个指针,同时出发,每次各走一步,它们必定会相遇,且第一次相遇的点就是环入口点。

代码实现:

public static Node findLoopPort(Node head) {
        Node slow = head;
        Node fast = head;
        //先判断该链表是否有环
        while(fast != null && fast.next !=null) {
            fast = fast.next.next;
            slow = slow.next;
            if(fast == slow) {
                break;
            }
        }
        if(fast == null || fast.next == null) {
            return null;
        }
        //如果链表有环,则将slow设置指向链表头,此时fast指向相遇点,然后同时开始移动,直到两个指针相遇
        slow = head;
        while(slow != fast) {
            slow = slow.next;
            fast = fast.next;
        }
        return slow;
    }


 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
判断一个链表是否有环可以使用快慢指针的方法,具体实现如下: ```c #include <stdio.h> #include <stdlib.h> struct ListNode { int val; struct ListNode *next; }; // 判断链表是否有环 bool hasCycle(struct ListNode *head) { if (head == NULL || head->next == NULL) { return false; // 链表为空或只有一个,必然无 } struct ListNode *slow = head; struct ListNode *fast = head->next; while (slow != fast) { if (fast == NULL || fast->next == NULL) { return false; // 快指针到达链表末尾,无 } slow = slow->next; fast = fast->next->next; } return true; // 快慢指针相遇,有环 } int main() { // 创建链表 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 3(形成一个) struct ListNode *head = (struct ListNode *)malloc(sizeof(struct ListNode)); head->val = 1; head->next = (struct ListNode *)malloc(sizeof(struct ListNode)); head->next->val = 2; head->next->next = (struct ListNode *)malloc(sizeof(struct ListNode)); head->next->next->val = 3; head->next->next->next = (struct ListNode *)malloc(sizeof(struct ListNode)); head->next->next->next->val = 4; head->next->next->next->next = (struct ListNode *)malloc(sizeof(struct ListNode)); head->next->next->next->next->val = 5; head->next->next->next->next->next = (struct ListNode *)malloc(sizeof(struct ListNode)); head->next->next->next->next->next->val = 6; head->next->next->next->next->next->next = head->next->next; // 入口是节 3 // 判断链表是否有环 bool has_cycle = hasCycle(head); if (has_cycle) { printf("链表有环\n"); } else { printf("链表\n"); } return 0; } ``` 输出结果为: ``` 链表有环 ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值