为什么快慢指针是2和1

principl 2014-10-29 10:11:58
大家应该都知道,在判断单向链表中是否存在环的问题中,比较优秀的解法就是采用快慢指针的方法。指针pfast从头出发每次走两步,指针pslow从头出发每次走一步,当两个指针相遇时,则存在环。
我的疑问是:为什么是走1步、走2步呢?原理是什么呢?我自己探索了半天没有解决,希望知道的朋友帮我解决下,谢谢了!
...全文
372 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
principl 2014-10-30
  • 打赏
  • 举报
回复
引用 17 楼 Saleayas 的回复:
我认为步长不能大于循环节点长度就可以了。
for (int i = 0; i < STEP; ++i)
{
fast = fast->next;
if (fast == slow)
{
return true;
}
}
步长不能大于循环节点长度就可以了,不太明白你的意思。
principl 2014-10-29
  • 打赏
  • 举报
回复
非常感谢大家,我明白了,真的非常感谢大家!!!
FancyMouse 2014-10-29
  • 打赏
  • 举报
回复
不是奇偶的问题。要点是2-1=1,所以每次只能缩小1格差距,所以总会碰上。你把1,2改成2,3或者3,4或者100,101都可以。不过1,2跑起来最快就是。 如果是2,7的话那如果环的长度正好整除5,但是你进环的时候正好错开的话那就永远检测不到了。
勤奋的小游侠 2014-10-29
  • 打赏
  • 举报
回复
引用 10 楼 LINUX2012LINUX 的回复:
引用 9 楼 lovesmiles 的回复:
[quote=引用 7 楼 LINUX2012LINUX 的回复:] [quote=引用 4 楼 lovesmiles 的回复:] 这个问题就像跑步,跑得快的人在前面。跑得慢的人在后面,然后跑着跑着居然跑得慢的人和跑得快的人跑到了同一个点,肯定是在围着圈跑,所以存在环。
跑步为实数模型,这个问题是自然数模型,有一定的区别。
你是想表达跑步是连续的,这个算法是离散的对吧?连续的必定有交点,离散的未必会有交点,是不是这个意思? 你显然没有理解这个1步和2步的巧妙之处。 两个人是在同一个点出发的,假如这是一个环,某个时刻,慢的和快的接近,然后超越,这中间是隔了一个点,刚好没有办法相交。好了,这是第一圈,没法子证明这是一个环。但是,第二圈,看好了,第二圈是从第一圈的基础上来开始的,这二个人的起点并不是同一个点,所以他们在下一圈时,肯定刚好会落在同一个点的。 你想明白,上次如果只相交时如果落后一步,第二次相交时肯定落后二步。奇奇肯得得偶。所以要么第一圈相交一点,要么在第二圈相交于一点。[/quote]恩,非常感谢你的回答,你说的很对,但是还有一个问题,为什么不是别的数字呢?比如2,7或者3,8之类的呢?[/quote] 其它数字当然也可以,只不过要跑到你傻而已,跑二轮就能确定的时候为什么要跑8轮?
principl 2014-10-29
  • 打赏
  • 举报
回复
引用 11 楼 zhao4zhong1 的回复:
Do not let me think! 比较简单直观的解法是map每个走过节点的地址值,有重复就有环。
映射走过的地址值,不太明白你的具体意思诶。
赵4老师 2014-10-29
  • 打赏
  • 举报
回复
Do not let me think! 比较简单直观的解法是map每个走过节点的地址值,有重复就有环。
principl 2014-10-29
  • 打赏
  • 举报
回复
引用 9 楼 lovesmiles 的回复:
引用 7 楼 LINUX2012LINUX 的回复:
[quote=引用 4 楼 lovesmiles 的回复:] 这个问题就像跑步,跑得快的人在前面。跑得慢的人在后面,然后跑着跑着居然跑得慢的人和跑得快的人跑到了同一个点,肯定是在围着圈跑,所以存在环。
跑步为实数模型,这个问题是自然数模型,有一定的区别。
你是想表达跑步是连续的,这个算法是离散的对吧?连续的必定有交点,离散的未必会有交点,是不是这个意思? 你显然没有理解这个1步和2步的巧妙之处。 两个人是在同一个点出发的,假如这是一个环,某个时刻,慢的和快的接近,然后超越,这中间是隔了一个点,刚好没有办法相交。好了,这是第一圈,没法子证明这是一个环。但是,第二圈,看好了,第二圈是从第一圈的基础上来开始的,这二个人的起点并不是同一个点,所以他们在下一圈时,肯定刚好会落在同一个点的。 你想明白,上次如果只相交时如果落后一步,第二次相交时肯定落后二步。奇奇肯得得偶。所以要么第一圈相交一点,要么在第二圈相交于一点。[/quote]恩,非常感谢你的回答,你说的很对,但是还有一个问题,为什么不是别的数字呢?比如2,7或者3,8之类的呢?
勤奋的小游侠 2014-10-29
  • 打赏
  • 举报
回复
引用 7 楼 LINUX2012LINUX 的回复:
引用 4 楼 lovesmiles 的回复:
这个问题就像跑步,跑得快的人在前面。跑得慢的人在后面,然后跑着跑着居然跑得慢的人和跑得快的人跑到了同一个点,肯定是在围着圈跑,所以存在环。
跑步为实数模型,这个问题是自然数模型,有一定的区别。
你是想表达跑步是连续的,这个算法是离散的对吧?连续的必定有交点,离散的未必会有交点,是不是这个意思? 你显然没有理解这个1步和2步的巧妙之处。 两个人是在同一个点出发的,假如这是一个环,某个时刻,慢的和快的接近,然后超越,这中间是隔了一个点,刚好没有办法相交。好了,这是第一圈,没法子证明这是一个环。但是,第二圈,看好了,第二圈是从第一圈的基础上来开始的,这二个人的起点并不是同一个点,所以他们在下一圈时,肯定刚好会落在同一个点的。 你想明白,上次如果只相交时如果落后一步,第二次相交时肯定落后二步。奇奇肯得得偶。所以要么第一圈相交一点,要么在第二圈相交于一点。
Saleayas 2014-10-29
  • 打赏
  • 举报
回复
去找你的数学老师,把学费拿回来。
principl 2014-10-29
  • 打赏
  • 举报
回复
引用 4 楼 lovesmiles 的回复:
这个问题就像跑步,跑得快的人在前面。跑得慢的人在后面,然后跑着跑着居然跑得慢的人和跑得快的人跑到了同一个点,肯定是在围着圈跑,所以存在环。
跑步为实数模型,这个问题是自然数模型,有一定的区别。
principl 2014-10-29
  • 打赏
  • 举报
回复
引用 1 楼 Saleayas 的回复:
想象一下,体育课的跑操场就可以了。
这个不同,体育场的连续的,你看着似乎类似,实际差别很大,这个问题中的数学模型是自然数,而体育场跑步是实数,差别很大。
Saleayas 2014-10-29
  • 打赏
  • 举报
回复
应该是跑得快的感觉在后面了,所以每一次 next 的时候都需要判断是否和 slow 相等。 fast 的步长不能大于 list 中的环大小,所以最简单为 2.
勤奋的小游侠 2014-10-29
  • 打赏
  • 举报
回复
这个问题就像跑步,跑得快的人在前面。跑得慢的人在后面,然后跑着跑着居然跑得慢的人和跑得快的人跑到了同一个点,肯定是在围着圈跑,所以存在环。
zybjtu 2014-10-29
  • 打赏
  • 举报
回复
当然是最慢的情况
zybjtu 2014-10-29
  • 打赏
  • 举报
回复
跑得快的总会追上跑得慢的 选速度1, 速度2的话,2圈就能相遇。
Saleayas 2014-10-29
  • 打赏
  • 举报
回复
想象一下,体育课的跑操场就可以了。
Saleayas 2014-10-29
  • 打赏
  • 举报
回复
我认为步长不能大于循环节点长度就可以了。
for (int i = 0; i < STEP; ++i)
{
fast = fast->next;
if (fast == slow)
{
return true;
}
}
principl 2014-10-29
  • 打赏
  • 举报
回复
引用 14 楼 FancyMouse 的回复:
不是奇偶的问题。要点是2-1=1,所以每次只能缩小1格差距,所以总会碰上。你把1,2改成2,3或者3,4或者100,101都可以。不过1,2跑起来最快就是。 如果是2,7的话那如果环的长度正好整除5,但是你进环的时候正好错开的话那就永远检测不到了。
永远检测不到的情况,这个怎么证明呢?你能详细说明一下吗?对于快慢指针到底是个什么情况啊?又让你给说糊涂了,

64,677

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧