判断一个链表是否有环,如果有环返回环开始的结点指针
2014-04-10 16:44
357 查看
LeetCode OJ :Linked List Cycle II
Given a linked list, return the node where the cycle begins. If there is no cycle, return
Follow up:Can you solve it without using extra space?
看到一个更牛叉的解法:这实际上是一个经典的龟兔赛跑问题。
假设:
x:环开始的索引结点
y:环的长度
兔的赛跑速度是龟的两倍
这样兔肯定在环内的某一点上追上龟,假设这一点为m
这样如果设龟走过的总路程为:x+ky+m,兔走过的总路程为:x+ty+m。则有:
让快指针停在两指针相遇的点,然后让慢指针回到头指针的位置,两个指针同时出发,每次走一步。
当慢指针走到环的第一个结点处(即走了x步),此时快指针距离环的第一个结点的位置为:x+m,即也在环的第一个结点处。所以此时两个指针又相遇了。
这样就可以判定环的第一个结点的位置了,即,两指针相遇的位置!
Given a linked list, return the node where the cycle begins. If there is no cycle, return
null.
Follow up:Can you solve it without using extra space?
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode *detectCycle(ListNode *head) { if((head == NULL) || (head->next == NULL)) return NULL; ListNode *p, *q; p = q = head; p = p->next; q = q->next->next; //指针追击问题 while((q != NULL) && (q->next != NULL) && (p != q)) { p = p->next; q = q->next->next; } if((q == NULL) || (q->next == NULL)) return NULL; else if(p == q) //链表肯定存在环 { int flag = 0; ListNode *r, *first; r = head; if((r == p) || (r == q)) //只包含头结点的环 return r; if(p->next == q->next->next)//只包含尾结点的环 return p; while((p != r) && (q != r)) { p = p->next; q = q->next->next; while(p != q) { if((p == r) || (q == r)) return r; p = p->next; q = q->next->next; } r = r->next; if((r == p) || (r == q)) return r; } } } };
看到一个更牛叉的解法:这实际上是一个经典的龟兔赛跑问题。
假设:
x:环开始的索引结点
y:环的长度
兔的赛跑速度是龟的两倍
这样兔肯定在环内的某一点上追上龟,假设这一点为m
这样如果设龟走过的总路程为:x+ky+m,兔走过的总路程为:x+ty+m。则有:
x+ty+m = 2(x+ky+m)故有:x+m = (t-2k)y。所以(x+m)mod y = 0,所以有如下方法:
让快指针停在两指针相遇的点,然后让慢指针回到头指针的位置,两个指针同时出发,每次走一步。
当慢指针走到环的第一个结点处(即走了x步),此时快指针距离环的第一个结点的位置为:x+m,即也在环的第一个结点处。所以此时两个指针又相遇了。
这样就可以判定环的第一个结点的位置了,即,两指针相遇的位置!
class Solution { public: ListNode *detectCycle(ListNode *head) { // IMPORTANT: Please reset any member data you declared, as // the same Solution instance will be reused for each test case. ListNode* slow = head; ListNode* fast = head; do{ if( !slow || !fast ) return NULL; slow = slow->next; fast = fast->next; if( fast ) fast = fast->next; else return NULL; }while( slow != fast ); slow = head; while( slow != fast ){ slow = slow->next; fast = fast->next; } return slow; } };
相关文章推荐
- 判断一个单链表是否有环。如果有,把指向环开始的指针返回;如果没有,返回NULL。
- 今天开始学Java 输入一个单向链表和一个节点的值,从单向链表中删除等于该值的节点,删除后如果链表中无节点则返回空指针。
- 判断链表是否成环,如果成环返回成环的第一个结点
- 有一个二叉树,现在怀疑它有一个结点有2个父节点,请写出一个函数来判断该二叉树是否存在一个节点含有2个父节点。如果存在,返回true,否则返回false。
- 有一个二叉树,现在怀疑它有一个结点有2个父节点,请写出一个函数来判断该二叉树是否存在一个节点含有2个父节点。如果存在,返回true,否则返回false。
- 判断链表是否有环,如果有返回入环的第一个节点。
- 如何判断一个链表是否有环,如果有环,并找出环的入口
- 判断链表是否有环,以及如果有环求环的长度和环开始的节点
- 【数据结构】单链表—判断一个链表是否形成了环形结构 — 快慢指针
- 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5
- 链表分割 编写代码,以给定值x为基准将链表分割成两部分,所有小于x的结点排在大于或等于x的结点之前 给定一个链表的头指针 ListNode* pHead,请返回重新排列后的链表的头指针。注意:分割以
- 建立一个带附加头结点的单链表.实现测长/打印/删除结点/插入结点/逆置/查找中间节点/查找倒数第k个节点/判断是否有环
- 判断一个字符串是否是回文,如果是,返回字符串“yes”,如果不是,返回字符串“no”
- 今天开始学Java 输入一个单向链表,输出该链表中倒数第k个结点,链表的倒数第1个结点为链表的尾指针。
- 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5
- 判断两个链表是否相交,如果相交如何找到第一个相交结点。
- 判断一个单项链表是否有循环,如果有循环输出循环点
- 给定一个循环链表,实现一个算法返回这个环的开始结点
- 请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。 例如 a b c e s f c s a d e e 矩阵中包含一条字符串"bccced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中
- 如何判断一个链表是否有环? 2、如果链表为存在环,如果找到环的入口点?