链表之快慢指针续
来源:互联网 发布:宿舍破解版路由器mac 编辑:程序博客网 时间:2024/05/31 00:40
之前解决了如何判断一个单链表是否存在环的问题。
那:如果要求出环的长度呢?
如果要求出环的入口点呢?
一、求出带环单链表环的长度
求长度,就是希望有个指针能够遍历环中的每一个元素,然后记下经过的节点数就好了。
当fast==slow的时候,fast和slow已经在环中了
第一种方法:用p记录下fast所指的节点,q从这个节点开始遍历,当q再次等于p的时候,说明已经在环里走了一圈了,经过的节点数就是环的长度。
int loopLength1(Node *head){ Node *slow, *fast; slow = fast = head; while(fast && fast -> next) { fast = fast -> next -> next; slow = slow -> next; if(fast == slow) break; } if(fast == slow) { Node *p = fast; Node *q = fast -> next; int length = 1; while(p != q) { q = q -> next; ++length; } return length; } return -1;}
第二种方法:fast 与 slow 第一次相遇开始计数,当它们第二次相遇时,我们可以证明,它们整整走了一圈,仍然指向第一次相遇时指向的节点。为了标记是否计数以及是否是第二次相遇,就需要用到两个bool类型的变量作为标记,分别是start 和 again
证明: 若环的长度为n, 第二次相遇时slow走了x步
那么一方面fast走了2x步,另一方面fast走了x+n步。所以x等于n 即它们刚好走了一圈,回到了原点
int loopLength2(Node *head){ Node *slow, *fast; slow = fast = head; bool start = false,again = false; int length = 0; while(fast && fast -> next) { fast = fast -> next -> next; slow = slow -> next; //如果再一次追赶上 if(fast == slow && again) break; //如果第一次追赶上,则进行第二次追赶 else if(fast == slow && !again) { start = true; again = true; } if (start) ++length; } if(fast == slow && again) return length; else return -1;}
二、求出环的入口点
这里有个论断,当fast slow第一次相遇时,slow一定还没有遍历完整个链表。自己画了几次发现是这样,具体证明没找到。设a是从head到入口点的长度,x是入口点到相遇点的长度,l是链表总长度
假设slow指针走了s步,则2s = s + nr, 得出s = nr ,又s = a + x
所以a + x = nr = (n-1)r + r = (n - 1)r + l - a
即 a + x = l - a - x
a= (n - 1)r + l - a - x
l - a - x指的是从相遇点到入口点的长度
a指的是从head到入口点的长度
这个式子表明:从head出发的指针与从fast 和 slow相遇点出发的指针一定会在某个点相遇,它们相遇之处就是环的入口处。
好吧,算法:当fast和slow相遇后,令slow = head,fast不变,两者继续向后移动,知道两指针相遇,相遇之处就是环的入口处。
Node *findLoopPort(Node *head){ Node *slow, *fast; slow = fast = head; while(fast && fast -> next) { fast = fast -> next -> next; slow = slow -> next; if(fast == slow) break; } if(fast == slow) { slow = head; while(fast != slow) { fast = fast -> next; slow = slow -> next; } return slow; } return NULL;}
- 链表之快慢指针续
- 链表追赶之快慢指针
- 链表操作之快慢指针
- 快慢链表和快慢指针
- 链表快慢指针应用
- 数据结构之快慢指针查找链表中间结点
- 快慢指针在链表的应用
- 快慢指针在链表的应用
- 快慢指针,链表的排序
- 快慢指针和链表原地反转
- 快慢指针在链表中的应用
- 链表的快慢指针:查找中点
- 快慢指针在链表的应用
- 链表的快慢指针:查找中点
- 快慢指针 —— 链表中点
- LintCode 带环链表(快慢指针法)
- 链表面试题之快慢指针问题(一) 查找链表中间节点
- 运用快慢指针判断链表是否有环
- 运用椭圆画法,45行代码画出任意正多边形
- Ubuntu中安装tftp服务的方法
- html基础内容
- HDU 4421 Bit Magic (图论-2SAT)
- 黑马程序员——String小结
- 链表之快慢指针续
- Myeclipse下新建struts项目并运行
- 如果,你是一个爱逐臭争利
- java中对象的复制
- 关于视觉显著性检测的思考(二)
- volley 应用 GET POST请求 图片异步加载
- Java输入输出(7)---向指定文件,指定位置插入内容
- 锱铢比较的人
- 那么,请到繁华闹市去