环路检测

题目描述

解题思路

图中紫色节点为相遇节点,若快慢指针相遇,必定满足如下关系:

  1. 我们使用两个指针,它们起始都位于链表的头部。随后慢指针每次向后移动一个位置,而快指针向后移动两个位置。如果链表中存在环,则快 指针最终将再次与 慢指针在环中相遇。

  2. 当慢指针进入环以后,慢指针还没走完一个环的时候,快指针必定与之相遇,此时快指针可能已经走了n次环了。因此走过的距离为:s=a+n*(b+c)+b

  3. 任意时刻,快指针走过的距离都是慢指针的两倍 所以 2*(a+b)=a+n*(b+c)+b 所以得出 a=nb+nc-b 即是 a=(n-1)b+nc 即是 a=c+(n-1)(b+c)

  4. 从3可知,慢指针走完a表示着快指针走完c加n-1圈周长,因此他们会在入口节点相遇。

解题代码如下

/**
 * @description:
 * @author: lilang
 * @version:
 * @modified By:[email protected]
 */
public class ListSolution {

    public ListNode detectCycle(ListNode head) {

        if (head == null) {
            return null;
        }

        ListNode goFast, goSlow;

        goFast = goSlow = head;

        boolean isCycle = false;

        while (goFast != null && goSlow != null) {

            goFast = goFast.next;

            if (goFast == null) {
                break;
            } else {
                goFast = goFast.next;
            }

            goSlow = goSlow.next;

            if (goFast == goSlow) {
                isCycle = true;
                break;
            }
        }

        if (!isCycle) {
            return null;
        }

        goSlow = head;

        while (goFast != goSlow) {
            goFast = goFast.next;
            goSlow = goSlow.next;

        }
        return goSlow;
    }

    public static void main(String[] args) {
        System.out.println(null == null);
    }
}

解题方法二

直接记录节点是否访问过,如果访问过表示存在环,否则不存在。

public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode pos = head;
        Set<ListNode> visited = new HashSet<ListNode>();
        while (pos != null) {
            if (visited.contains(pos)) {
                return pos;
            } else {
                visited.add(pos);
            }
            pos = pos.next;
        }
        return null;
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章