/*
* **************************************************************************
* ******************** ********************
* ******************** COPYRIGHT INFORMATION ********************
* ******************** ********************
* **************************************************************************
* *
* _oo8oo_ *
* o8888888o *
* 88" . "88 *
* (| -_- |) *
* 0\ = /0 *
* ___/'==='\___ *
* .' \\| |// '. *
* / \\||| : |||// \ *
* / _||||| -:- |||||_ \ *
* | | \\\ - /// | | *
* | \_| ''\---/'' |_/ | *
* \ .-\__ '-' __/-. / *
* ___'. .' /--.--\ '. .'___ *
* ."" '< '.___\_<|>_/___.' >' "". *
* | | : `- \`.:`\ _ /`:.`/ -` : | | *
* \ \ `-. \_ __\ /__ _/ .-` / / *
* =====`-.____`.___ \_____/ ___.`____.-`===== *
* `=---=` *
* **************************************************************************
* ******************** ********************
* ******************** ********************
* ******************** 佛祖保佑 永远无BUG ********************
* ******************** ********************
* **************************************************************************
*/
目录
判断环形链表
给定一个链表的头节点
head
,返回链表开始入环的第一个节点。 如果链表无环,则返回null
。如果链表中有某个节点,可以通过连续跟踪
next
指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数pos
来表示链表尾连接到链表中的位置(索引从 0 开始)。如果pos
是-1
,则在该链表中没有环。注意:pos
不作为参数进行传递,仅仅是为了标识链表的实际情况。不允许修改 链表。
示例 1:
输入:head = [3,2,0,-4], pos = 1 输出:返回索引为 1 的链表节点 解释:链表中有一个环,其尾部连接到第二个节点。示例 2:
输入:head = [1,2], pos = 0 输出:返回索引为 0 的链表节点 解释:链表中有一个环,其尾部连接到第一个节点。示例 3:
输入:head = [1], pos = -1 输出:返回 null 解释:链表中没有环。提示:
- 链表中节点的数目范围在范围
[0, 10000]
内-100000 <= Node.val <= 100000
pos
的值为-1
或者链表中的一个有效索引进阶:你是否可以使用
O(1)
空间解决此题?
(一)题解:
链表只有两种情况:
——不带环:由于不带环非常容易判断(pcur->next == NULL)终止循环即可,这里不给出不带环链表的情况。
——带环:画图表示一个带环链表 :
这里先不解释为什么要用快慢指针法,对为什么要用快慢指针放在后面讨论;
创建快慢指针->
快指针:fast
慢指针:slow
创建快慢指针。由于快指针每次走两步,慢指针每次走一步,所以当快指针走到环起始节点时,慢指针还在环前单链表的半程位置:
当慢指针进入环时,快指针已经在环中走了一会儿了。
我们设此时快慢指针之间的距离为D(distance),单串链表长度为L,环形链表的周长为C,则另一半优弧的长度为C-D,由于快慢指针都在绕圈,于是这个问题就演变成了追及问题。
(这里暂且把节点数称为长度)
由于快指针每次走两步,慢指针每次走一步,快慢指针的速度差为1,那么不论D是什么值,每次两指针间的距离减小1,于是距离为D,D-1,D-2,D-3……2,1,0(追上)。
最终追上:
由于速度差v是 常数1,1是任何数的因子,所以D一定可以平缓的逐渐减小到0,减小到0就意味着追上了。这样就解释清楚了为什么快2慢1一定可以追上。
对于整个过程:
slow的路程 = L + X;
fast的路程 = L + n*C + X
得到等式:
slow的路程*2=fast的路程->:2*(L+X) = L + n*C + X
化简得:
L = n*C - X
不妨设:n等于1;
L = C - X
那么,环形链表中剩余的节点数就等于L的节点数,我们就可以在找到相遇节点后用meet指针记录下来,接下来用判断链表相交的方法来找到环的第一个节点:
代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
typedef struct ListNode LS;
struct ListNode *detectCycle(struct ListNode *head) {
LS *fast = head;
LS *slow = head;
int f = 0;
while(fast && fast->next)
{
fast = fast ->next ->next;
slow = slow->next;
if(fast == slow)
{
LS* meet = slow;
while(meet != head)
{
meet = meet->next;
head = head->next;
}
return meet;
}
}
return NULL;
}
完~
未经作者同意禁止转载