单链表(内部循环的问题)

来源:互联网 发布:淘宝买家怎么贷款啊 编辑:程序博客网 时间:2024/06/05 11:51

一,问题描述
1,一个单链表,判断内部有没有循环;
2,如果有循环,求出这个循环的长度;
3,如果有循环,找到这个循环的第一个点(和解除环是一个问题);

二、问题分析
1,方法一:这道题目最容易想到的是暴力求解法,复杂度O(n^2)。使用两个指针a, b。a从表头开始一步一步往前走,遇到null则说明没有环,返回false;a每走一步,b从头开始走,如果遇到b==a.next,则说明有环true,如果遇到b==a,则说明暂时没有环,继续循环。下面会用这种方法实现问题3。

2,方法二:用数学求解出关系(关系如下图):
使用两个指针slow,fast。两个指针都从表头开始走,slow每次走一步,fast每次走两步,如果fast遇到null,则说明没有环,返回false;如果slow==fast,说明有环,并且此时fast超了slow一圈,返回true。

为什么有环的情况下二者一定会相遇呢?因为fast先进入环,在slow进入之后,如果把slow看作在前面,fast在后面每次循环都向slow靠近1,所以一定会相遇,而不会出现fast直接跳过slow的情况。
这里写图片描述

三、java代码
1,暴力求解问题三:

public static ListNode detectCycle(ListNode head) {        if(head == null) {            return null;        }        ListNode fast = head.next;        ListNode slow = head;        while(fast != null) {            slow = head;            while(slow != fast) {                if(slow == fast.next)                    return slow;                slow = slow.next;            }            fast = fast.next;        }        return null;    }

2,数学求解问题三:

public static ListNode detectCycle2(ListNode head) {        ListNode fast = head;        ListNode slow = head;        while(fast != null && fast.next != null) {            slow = slow.next;            fast = fast.next.next;            if(slow == fast)                break;        }        if(fast == null || fast.next == null ) {            return null;        }else {            slow = head;            while(slow != fast) {                slow = slow.next;                fast = fast.next;            }            return slow;        }    }

3,求解问题1,2:只需要在求解问题三中记录走过的数量就可以了。

原创粉丝点击