环形链表

问题一

给定一个链表,判断链表中是否有环。

解题思路:

可以设定两个指针p与q,初始都指向链表的起始点(head),p每次跳一步而q每次两步。

若链表中存在环,则p与q一定相遇。

代码如下:

    public static boolean hasCycle(ListNode head) {

        if (head == null) return false;
        ListNode p = head;
        ListNode q = head;
        while (true) {
            if (q == null || q.next == null) return false;
            p = p.next;
            q = q.next.next;
            if (p == q) return true;
        }
    }

问题二

给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

解题思路:

设定两个指针p与q,初始都指向链表的起始点(head),p每次跳一步而q每次两步。

设链表中非环节点由m个,环节点有n个。

当p指针到达环的第一个节点时,p与q都位于环中,p跳了m步,q跳了2m步,p与q相距m步,q与p相距n-m步。

(如上图所示,m=3,n=7 。当p跳3步到达环的第一个节点时,p与q相距3步,q与p相距4步。)

由于q每次必p多走一步,故两个指针需要再跳n-m次才能相遇。此时相遇点与环的起始点相距m步,而head与环的起始点也相距m步。

故head每次跳一步,p每次跳一步,二者的相聚点即是环的第一个节点。

 代码如下:

    public static ListNode detectCycle(ListNode head) {

        if (head == null) return null;
        ListNode p = head;
        ListNode q = head;
        while (true) {
            if (q == null || q.next == null) return null;
            p = p.next;
            q = q.next.next;
            if (p == q) break;
        }

        while (head != q) {
            head = head.next;
            q = q.next;
        }
        return head;
    }

猜你喜欢

转载自www.cnblogs.com/deltadeblog/p/9180183.html