在上篇文章--"检测链表中是否存在循环"(http://blog.youkuaiyun.com/iccav/article/details/11682089)中介绍了如何检测链表中的循环,这篇文章介绍一下如果消除循环。
图片来自(http://www.crazyforcode.com/write-program-detect-loop-linked-list/)
问题描述:
假设我们有一个链表,链表中存在循环,我们如何消除循环?即如何找到链表的尾部(在本图中是5),并将循环尾部的next指针设为NULL。
思路:
先推导一个我们要用到的结论。
假设链表中直链部分的长度为m(链表中的非循环部分,在本图中是2),链表中循环部分的长度为n(在本图中是3)。同样是用两个指针,一个fast,一个slow。由于两个指针都是从头部开始移动的,fast指针的移动速度是slow移动速度的两倍,故若存在循环,则当两个指针相遇时,fast指针的移动的长度应该是slow指针移动长度的两倍。假设slow的移动长度为length,则fast指针移动的长度是2*length。假设fast和slow相遇时,距离循环头部的长度为k(在本图中循环的头部是指3号节点)则有如下等式:
leng = m + p*n + k 其中p是指在两指针相遇之前,slow指针已经在循环中走完了p次
2*length = m + q*n + k 其中q是指在两指针相遇之前,fast指针已经在循环中走完了q次
消去length,得到等式
m = (q-2p)*n - k
现在如果我们将fast指针定位到链表的头部,slow此时仍然在fast和slow相遇的位置,将fast和slow指针同时向右移动,每次都移动一步。当fast移动了m步时,由于fast此次是从链表的头部开始