判断单链表是否存在环及寻找环的入口点
2016-03-16 23:55
302 查看
判断链表是否存在环,有如下几种解法:1. 遍历链表,将已经遍历过的节点放在一个hash表中,如果一个节点已经存在hash表中,说明有环。时间:O(n) 空间:O(n)2. 反转链表。使用反转链表的方法, 每过一个节点就把该节点的指针反向。若存在环,反转next指针最终会走到链表头部。若没有环,反转next指针会破坏链表结构(使链表反向), 所以为还原链表,需要把链表再反向一次。 这种方法的空间复杂度是O(1), 实事上我们使用了3个额外指针;而时间复杂度是O(n), 我们最多2次遍历整个链表(当链表中没有环的时候)3. 使用快慢指针 寻找环的入口点: 当fast按照每次2步,slow每次一步的方式走,发现fast和slow重合,确定了单向链表有环路。接下来,让fast回到链表的头部,重新走,每次步长1,那么当fast和slow再次相遇的时候,就是环路的入口了。证明:在fast和slow第一次相遇的时候,假定slow走了n步,环路的入口是在p步,那么 slow走的路径: p+c = n; c为fast和slow相交点 距离环路入口的距离 fast走的路径: p+c+k*L = 2*n; L为环路的周长,k是整数 显然,如果从p+c点开始,slow再走n步的话,还可以回到p+c这个点。 同时,fast从头开始走,步长为1,经过n步,也会达到p+c这点。 显然,在这个过程中fast和slow只有前p步骤走的路径不同。所以当p1和p2再次重合的时候,必然是在链表的环路入口点上。
slist * FindLoopPort(slist * head){slist * slow = head, * fast = head;while ( fast && fast -> next ){slow = slow -> next;fast = fast -> next -> next;if ( slow == fast ) break ;}if (fast == NULL || fast -> next == NULL)return NULL;slow = head;while (slow != fast){slow = slow -> next;fast = fast -> next;}
相关文章推荐
- BillBoardView自定义控件广告板轮播
- 【LeetCode题意分析&解答】38. Count and Say
- 矩形覆盖
- SQL Server实现类似于自动刷新数据的功能
- JDBC知识 - 马士兵视频教程笔记
- (R)?ex - A simple framework to simplify system administration and datacenter automation
- 【C】由printf("%d\t%d\t%d\n",a,a+=(a++),a);引起的思考
- xdotool源代码,需要的伙伴请自取
- 变态跳台阶
- 51NOD1515 明辨是非
- 不在编辑状态下的UITableView多选
- 多个Fragment之间的切换
- Ubuntu下的Android Studio某些开发问题
- 跳台阶
- 《FPGA NiosII篇》Part 1工程创建与注意点
- exit() 时或之后还能继续执行php代码的几种办法
- 重建二叉树
- js函数节流-性能-resize
- mysql外键,索引等基本操作 和 跨表复制数据操作
- mysql外键,索引等基本操作 和 跨表复制数据操作