原文:
Given a circular linked list, implement an algorithm which returns node at the beginning of the loop.
DEFINITION
Circular linked list: A (corrupt) linked list in which a node’s next pointer points to an earlier node, so as to make a loop in the linked list.
EXAMPLE
Input: A -> B -> C -> D -> E -> C [the same C as earlier]
Output: C
译文:
给定一个循环链表,实现一个算法返回这个环的开始结点。
定义:
循环链表:链表中一个结点的指针指向先前已经出现的结点,导致链表中出现环。
例子:
输入:A -> B -> C -> D -> E -> C [结点C在之前已经出现过]
输出:结点C
同http://blog.csdn.net/fightforyourdream/article/details/14639657
思路就不说了,有几点说明:
1)在快指针追击慢指针时,如何保证快指针不会跨过慢指针而不会重合?
快指针总是能和慢指针重合,为什么?因为如果假如真的“跨过了”,那么慢指针在i位置,快指针在i+1位置。但是考虑上一步,慢指针必定在i-1位置,快指针也在i-1位置,所以在上一步时已经重合了!
2)为什么相遇时通过重置慢指针,然后让快慢指针以相同速度前进,再次相遇就是环的开始点?
这就要分析一下走的过程了。因为快指针走的速度是慢指针的两倍,那么如果慢指针走p步,则快指针走了2p步。现在假设环的开始节点距离head节点有k个距离,则当慢指针走了k步时,慢指针正好到环的开始节点D,与此同时,快指针也走了2k步,前k步走在环外,后k步走在环内。由于k可能比环的长度还大,所以我们让k = k % LOOP_SIZE。
现在有如下的结论:
- 慢指针在环的开始处
- 快指针在超前环k步的位置上
- 慢指针落后k步于快指针
- 快指针落后 LOOP_SIZE - k 步于慢指针!
- 快指针以慢指针2倍的速度追击慢指针。或者说快指针以1步的相对速度追击相对静止的慢指针。则需要LOOP_SIZE-k 才能追上慢指针。在I位置追上。
D -> I 的距离是 LOOP_SIZE - k, I -> D 的距离是k,这段距离恰好和A->D的距离相同,都是k !!!那么把慢指针放在head节点A,然后两个指针以相同速度前进,相遇处就是环的开始节点。
3)一个推论:快慢指针第一次相遇的地方和head的距离是环长度的整数倍。
假设相遇处离环开始点相距x个点,环长度为n个点
慢指针:k+qn+x=m (1)
又有2m-m=m=pn (2)
有(1),(2)可得:k+qn+x=pn
所以k+x = (p-q)n,即相遇处离head的距离为环长的整数倍.
所以将其中一个指针移至head,同时两指针以相同速度再次相遇即为环的开始处.
package LinkLists;
import CtCILibrary.LinkedListNode;
public class S2_6 {
public static void main(String[] args) {
}
public LinkedListNode detectCycle(LinkedListNode head) {
if(head == null || head.next ==null){
return null;
}
LinkedListNode slow = head;
LinkedListNode fast = head;
// 找到第一次相遇点
while(fast!=null && fast.next!=null && slow!=null){
slow = slow.next;
fast = fast.next.next;
if(slow == fast){ // 相遇
break;
}
}
// 检查是否因为有环退出或是因为碰到null而退出
if(slow==null || fast==null || fast.next==null){
return null;
}
// 把慢指针移到链表头,然后保持快慢指针同样的速度移动
// 再次相遇时即为环的入口
slow = head;
while(slow != fast){
slow = slow.next;
fast = fast.next;
}
// 现在快慢指针都指向环的入口
return slow;
}
}
分享到:
相关推荐
1.判断链表是否有环: P1 P2 从头部出发,P1走两步,P2走一步,如果可以相遇,则环存在 2.从环内某个节点开始计数,再回到此节点时得到链表环的长度 le
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。 2、代码详解 寻找链表中环的入口结点主要分成三个步骤: 首先是设置两个快慢指针,如果快慢指针相遇,则快慢指针必然都在环中; 然后从...
循环链表 实现约瑟夫环 java 自己写的 测试通过 有注释
使用c语言中的循环链表及结构体实现约瑟夫环问题
看到题目后的主要思路:先判断链表是否为环,若为环再进行环入口的判断,否则直接返回null 1.判断链表是否为环形链表相对容易,代码如下。主要思路是创建两个指针–快指针fast,步长为2;慢指针slow,步长为1。若...
142. 环形链表 II方法:快慢双指针环问题:环入口第一步找到慢指针 slow 和快指针 fast 在环内的相遇点第二步查找指针在原点和慢指针在相遇点同时出发
附件是使用双指针发判断链表有环的代码实现,在Java中,判断单链表是否有环的经典方法是使用Floyd的“龟兔赛跑”算法,也称为快慢指针法。这种方法利用两个指针,一个每次走一步(称为慢指针),另一个每次走两步...
约瑟夫环 动态链表 处理 C
链表相关问题的完整代码,...**2、寻找环的入口点** **3、计算环的节点数** **4、计算(有环)链表的节点数** **5、找出环中距任意一点最远的节点** **6、判断两个无环链表是否相交** **7、寻找两个链表的相交的节点**
数据结构 约瑟夫环的链表实现 可以用链表的方法实现对约瑟夫环的具体操作
数据结构 初始化链表,插入删除节点,遍历链表,链表长度,找出中间节点
自己写的链表,并用链表解决了约瑟夫环问题,大家给个意见,主要是链表
用链表实现约瑟夫环,可以直接执行,编程语言为C++,适合初学者。
学习严蔚敏的数据结构课程时老师布置的实践作业,约瑟夫环,用链表实现,也可用顺序表实现,但是因为该环用顺序表实现时也无法实现随机访问,因此本人认为约瑟夫环的顺序表实现方法没有什么价值!在VC6.0下编译通过...
这里有两个资源,一个简易版的,一个扩展版(链表的增加、修改、查询、删除),还有论文(一个是约瑟夫环,一个是系数矩阵)。
用循环链表的方式实现约瑟夫环,下面是部分代码, typedef struct node { int key; int seatnum; struct node *next; }node,*linklist; void createlist(linklist&l,int n) { l=(linklist)malloc(sizeof(node));...
约瑟夫环,用循环链表实现,语言为Java。假设数到三的数出列。程序输出1到10的出列顺序。
通过循环链表实现约瑟夫环问题,用c语言实现。属于数据结构部分内容
单向循环链表实现约瑟夫环.zip
这是用数组表示循环链表,解决约瑟夫环的问题。匹配的报告实验报告随后上传。