常考数据结构和算法:链表中环的入口节点

题目描述

对于一个给定的链表,返回环的入口节点,如果没有环,返回null。

 

步骤: 
<1> 定义两个指针p1和p2,在初始化时都指向链表的头节点。 
<2> 如果链表中的环有n个节点,指针p1先在链表上向前移动n步。 
<3> 然后指针p1和p2以相同的速度在链表上向前移动直到它们相遇。 
<4> 它们相遇的节点就是环的入口节点。 
    那么如何得到环中的节点数目?即通过一快一慢两个指针来解决这个问题。当两个指针相遇时,表明链表中存在环。两个指针相遇的节点一定是在环中。可以从这个节点出发,一边继续向前移动一边计数,当再次回到这个节点时,即可得到环中的节点数了。

public class TestIsCircleList {
    public static void main(String[] args) {
        TestIsCircleList t = new TestIsCircleList();
        ListNode a = new ListNode(1);
        ListNode b = new ListNode(2);
        ListNode c = new ListNode(3);
        ListNode d = new ListNode(4);
        ListNode e = new ListNode(5);
        ListNode f = new ListNode(6);
        ListNode g = new ListNode(7);
        a.next = b;
        b.next = c;
        c.next = d;
        d.next = e;
        e.next = f;
        f.next = g;
        g.next = d;  // 形成环状
        //boolean isHave = t.hasCycle(a);
        //System.out.println(isHave);
        detectCycle(a);
    }


public static ListNode detectCycle(ListNode head) {
        ListNode slow = head; // 慢指针
        ListNode fast = head; // 快指针

        boolean isHaveCirle = false;
        while(null != fast && null != fast.next){
            slow = slow.next;
            fast = fast.next.next;

            if(slow == fast){
                // 通过一快一慢两个指针来解决这个问题。当两个指针相遇时,表明链表中存在环
                System.out.println("链表有环");
                isHaveCirle = true;
                break;
            }
        }

        if(!isHaveCirle){
            return null;
        }

        int circleCount = 1;
        slow = slow.next;
        // 求环的节点数
        while(fast != slow){
            circleCount++;
            // 一继续向前移动一边计数,当再次回到这个节点时,即可得到环中的节点数了
            slow = slow.next;
        }

        ListNode pre = head;
        ListNode post = head;
        for(int i=0;i

 

 

 

 

 

你可能感兴趣的:(算法)