您的位置:首页 > 其它

leetcode-Linked List Cycle I & II

2014-09-08 12:36 441 查看
继续刷题,虽然是水水得有空有兴趣了才上来刷两道,但还是希望坚持刷下去。

这次的两道题是Linked List Cycle,就是判断一个单向链表有没有换,第二道要求有环的话,输出环首的节点,当然题目对使用的空间有要求(原句是:Can you solve it without using extra space?
好想说:-  - no)。

还在看题目就被旁边的众大神们告知,这是经典题目啦,快慢指针轻松解出来啊,还可以证明的啦,blablabla.......于是又乖乖得去看经典解法了。哎 -  - 没网络怎么办啊。

解法大致为:用两个指针,一个一次跑1步,一个一次跑2步,如果快指针能追上慢指针,就说明有环,如果快指针先到了链表尾部说明没有环,but 为什么一个一次2步一个一次1步有环就一定能追上呢?解释如下:因为快指针每次2步,慢指针每次1步,那如果有环的情况下,2者之间的距离没经过一次循环就减少1步的距离,所以如果有环就一定会相遇。但要找到环的开头的话,就需要另外的方法了,具体做法是:当快慢指针相遇时,让快指针从链表头和慢指针一起重新开始遍历,两者都是每次一步,当2者再次相遇时,所指向的节点就是环的头节点了。证明如下:第一次相遇时,慢指针走了n=p+c(p为入环前的长度,c为环起点到两个指针相遇点的距离);快指针走了2n=p+c=kl(快指针的速度是慢指针的两倍,走的路程必然是2n,快指针重复了慢指针的p+c路程,又多走了整数个环的长度,k为整数,l为环的长度),所以可以得到n=p+c=kl,即kl-c=p,即此时慢指针从链表头重新开始按速度1来走,走p步,慢指针一定也到环的开头的快指针相遇,这样就能找到环的开头了,bingo。

原谅我文字水平太渣,还是上代码吧:

检测是否有环:

<span style="font-size:10px;">public class Solution {
public boolean hasCycle(ListNode head) {
if(head == null || head.next == null){
return false;
}
ListNode p1 = head.next;
ListNode p2 = head.next.next;
while(p1 != p2 && p2 != null && p2.next != null){
p1 = p1.next;
p2 = p2.next.next;
}
if(p2 == null || p2.next == null){
return false;
}else{
return true;
}
}
}</span>
检测环并找到环的入口:

<span style="font-size:10px;">public class Solution {
public ListNode detectCycle(ListNode head) {
if(head == null || head.next == null){
return null;
}
ListNode p1 = head.next;
ListNode p2 = head.next.next;
while(p1 != p2 && p2 != null && p2.next != null){
p1 = p1.next;
p2 = p2.next.next;
}
if(p2 == null || p2.next == null){
return null;
}else{
p2 = head;
while(p2 != p1){
p1 = p1.next;
p2 = p2.next;
}
return p2;
}
}
}</span>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息