一 初步解法
原帖:http://hi.baidu.com/_00000000/blog/item/9688a3895bb817759f2fb460.html
判断一个单向链表是否是循环链表比较简单,只要将一个指针p指向表的第一个节点,而另外一个指针q指向
p的下一个节点,然后让q向后滑动,直到q为0或q等于p(此时表是循环链表)为止。
而判断一个单向链表是否有环有点儿麻烦,因为链表的最后一个节点可能不是指向链表的头结点而是其他节点.
考虑网上流行的步长法:
p=head
q=head
while(p && q && q->next)
{
p=p->next; q=q->next->next
if (p==q)
return true
}
return 0;
正确性如下:
设链表的循环部分为W1,W2,..,Wn,...,W2n.(先假设循环部分的节点数为偶数)
设p第一次指向节点W1时, q指向Wk(2<=k<=n), 假设n-k为偶数,则经过(n-k)/2次迭代后, q指向Wn,p指向第
1+(n-k)/2 个节点. 设经过x次迭代,两个节点两个指针相遇, 即1+(n-k)/2 + x= 2x, 从而x=1+(n-k)/2, 相遇的位置为
2+n-k. 由于2<=k<=n, 因此2<=2+n-k<=n此后当p第一次指向节点n+1时,q再次指向W2.
然后p和q在节点W2n处相遇。
节点数目为奇数时的情形类似。
而判断一个单向链表是否有环有点儿麻烦,因为链表的最后一个节点可能不是指向链表的头结点而是其他节点.
考虑网上流行的步长法:
p=head
q=head
while(p && q && q->next)
{
p=p->next; q=q->next->next
if (p==q)
return true
}
return 0;
正确性如下:
设链表的循环部分为W1,W2,..,Wn,...,W2n.(先假设循环部分的节点数为偶数)
设p第一次指向节点W1时, q指向Wk(2<=k<=n), 假设n-k为偶数,则经过(n-k)/2次迭代后, q指向Wn,p指向第
1+(n-k)/2 个节点. 设经过x次迭代,两个节点两个指针相遇, 即1+(n-k)/2 + x= 2x, 从而x=1+(n-k)/2, 相遇的位置为
2+n-k. 由于2<=k<=n, 因此2<=2+n-k<=n此后当p第一次指向节点n+1时,q再次指向W2.
然后p和q在节点W2n处相遇。
节点数目为奇数时的情形类似。
二 改进的分析方法
直接使用数学公式证明正确性:
p位置为0 q位置为k,经过 x次迭代,相遇。设环的总长度为m
即(0+x)mod(m)==(k+2x)mod(m)
得到x=m-k。
对否??