LintCode: 帶環連結串列 + 帶環連結串列 II
阿新 • • 發佈:2019-02-07
1. 帶環連結串列
描述
給定一個連結串列,判斷它是否有環。
樣例
給出 -21->10->4->5, tail connects to node index 1,返回 true
挑戰
不要使用額外的空間
思路: 可以先看上面這個圖,a 是 起點,b 是 環的起點,b到d是一個環。
這個c點是什麼呢,下面我們來說說。
首先連結串列的題目,我們首先會想到快慢指標,沒錯,這道題就用到了快慢指標。 c 就是快慢指標第一次相遇的 那個地點。
x代表起點a到環的起點b的距離,y代表環的起點到第一次相遇地點c的距離, z代表環剩下的長度。 長度l 代表環的長度,
即 y+z。
再看下面兩個公式: v代表 慢指標走的長度, 2v代表 快指標走的長度。
v = x +y + m * l
2v = x + y + n * l
運算上面兩個式子,可以得到:
x + y = (n-2m)*l
繼續運算,可以得到:
x = (n-2*m-1)*l + l - y = (n-2*m-1)*l + z.
可以知道,x的長度是任意環的長度加上z的長度,那麼現在一個點從a開始出發,一個點從c點出發,每次前進一步,等它們相遇的時候,就正好在起點b處了。
2. 帶環連結串列 II
描述
給定一個連結串列,如果連結串列中存在環,則返回到連結串列中環的起始節點,如果沒有環,返回null。
樣例
給出 -21->10->4->5, tail connects to node index 1 ,返回10
挑戰
不使用額外的空間
題目 1, 2 的思路都在上邊了,下面給出Java實現程式碼:
1.
public boolean hasCycle(ListNode head) { // write your code here ListNode fast = head; ListNode slow = head; while (fast!=null && fast.next!=null){ slow = slow.next; fast = fast.next.next; if(slow==fast){ return true; } } return false; }
2.
public ListNode detectCycle1(ListNode head) {
// write your code here
if(head==null || head.next==null || head.next.next==null){
return null;
}
boolean flag = false;
ListNode fast = head;
ListNode slow = head;
while (fast!=null && fast.next!=null){
slow = slow.next;
fast = fast.next.next;
if(slow==fast){
flag = true;
break;
}
}
if(flag){
while (head != slow){
head = head.next;
slow = slow.next;
}
return head;
}
return null;
}