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