環路檢測

題目描述

解題思路

圖中紫色節點爲相遇節點,若快慢指針相遇,必定滿足如下關係:

  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;
    }
}

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