判断单链表是否有环?如何找到环的“起始”点?如何知道环的长度?
2017-03-06 15:36
330 查看
算法思想:
先分析是否有环。为此我们建立两个指针,从header一起向前跑,一个步长为1,一个步长为2,用while(直到步长2的跑到结尾)检查两个指针是否相等,直到找到为止。
那又如何知道环的长度呢?
根据上面的算法,在返回true的地方,也就是2个指针相遇处,这个位置的节点P肯定位于环上。我们从这个节点开始先前走,转了一圈肯定能回来:
继续我们的讨论,如何找到环的“起始”点呢?
延续上面的思路,我们仍然在返回true的地方P,计算一下从有环单链表的表头head到P点的距离。
如果我们把环从P点“切开”(当然并不是真的切,那就破坏原来的数据结构了),那么问题就转化为计算两个相交“单链表”的交点。一个单链表是从P点出发,到达P(一个回圈),距离M;另一个单链表从有环单链表的表头head出发,到达P,距离N。
先分析是否有环。为此我们建立两个指针,从header一起向前跑,一个步长为1,一个步长为2,用while(直到步长2的跑到结尾)检查两个指针是否相等,直到找到为止。
static bool JudgeCircleExists(Link head) { Link first = head; //1 step each time Link second = head; //2 steps each time while (second.Next != null && second.Next.Next != null) { second = second.Next.Next; first = first.Next; if (second == first) return true; } return false; }
那又如何知道环的长度呢?
根据上面的算法,在返回true的地方,也就是2个指针相遇处,这个位置的节点P肯定位于环上。我们从这个节点开始先前走,转了一圈肯定能回来:
static int GetCircleLength(Link point) { int length = 1; Link curr = point; while (curr.Next != point) { length++; curr = curr.Next; } return length; }
继续我们的讨论,如何找到环的“起始”点呢?
延续上面的思路,我们仍然在返回true的地方P,计算一下从有环单链表的表头head到P点的距离。
static int GetLengthFromHeadToPoint(Link head, Link point) { int length = 1; Link curr = head; while (curr != point) { length++; curr = curr.Next; } return length; }
如果我们把环从P点“切开”(当然并不是真的切,那就破坏原来的数据结构了),那么问题就转化为计算两个相交“单链表”的交点。一个单链表是从P点出发,到达P(一个回圈),距离M;另一个单链表从有环单链表的表头head出发,到达P,距离N。
private static Link FindIntersect(Link head) { Link p = null; //get the point in the circle bool result = JudgeCircleExists(head, ref p); if (!result) return null; Link curr1 = head.Next; Link curr2 = p.Next; //length from head to p int M = 1; while (curr1 != p) { M++; curr1 = curr1.Next; } //circle length int N = 1; while (curr2 != p) { N++; curr2 = curr2.Next; } //recover curr1 & curr2 curr1 = head.Next; curr2 = p.Next; //make 2 links have the same distance to the intersect if (M > N) { for (int i = 0; i < M – N; i++) curr1 = curr1.Next; } else if (M < N) { for (int i = 0; i < N – M; i++) curr2 = curr2.Next; } //goto the intersect while (curr1 != p) { if (curr1 == curr2) { return curr1; } curr1 = curr1.Next; curr2 = curr2.Next; } return null; }
相关文章推荐
- 8.判断单链表是否有环?如何找到环的“起始”点?如何知道环的长度?
- 如何判断单链表中是否有环?如何找到环中的起始节点
- 判断单链表是否有环,以及如何找起始点,环的长度
- 数据结构之链表面试题汇总(三)判断单链表是否有环、取出环的起始点、得到有环链表中环的长度
- 如何判断单链表是否有环,如果有怎么找到进入环的节点
- 如何判断单链表是否有环、环的入口、环的长度和总长
- 【算法分析】如何理解快慢指针?判断linked list中是否有环、找到环的起始节点位置。以Leetcode 141. Linked List Cycle, 142. Linked List Cycle II 为例Python实现
- 如何判断单链表是否出现环
- 判断单链表中是否有环,找到环的入口节点
- 判断单链表是否带环? 若带环, 求环的长度? 求环的入口点?
- 判断单链表中是否有环,找到环的入口节点
- 如何快速找到未知长度单链表的中间节点
- 算法面试题:如何判断单链表中是否存在环
- 你如何知道你是否真正找到了你爱的人?
- 如何判断单链表是否存在环 & 判断两链表是否相交
- 如何判断单链表里面是否有环【转载】
- 单链表的创建和遍历、求单链表中节点的个数、查找单链表中的中间结点、判断单链表是否有环、取出有环链表中环的长度,删除有序链表中的重复结点
- 笔试题:如何判断单链表是否存在环
- 面试笔试系列-1 判断单链表是否存在环,找到环入口
- 如何判断一个C++对象是否在堆栈上(通过VirtualQuery这个API来获取堆栈的起始地址,然后就可以得到答案了),附许多精彩评论