首页 > 学院 > 开发设计 > 正文

快慢指针和其简单应用

2019-11-08 02:34:05
字体:
来源:转载
供稿:网友

什么是快慢指针?

快慢指针中的快慢指的是移动的步长,即每次向前移动速度的快慢。例如可以让快指针每次沿链表向前移动2次,慢指针每次向前移动1次。

快慢指针的常见应用

1.判断单链表是否为循环链表

       对于初学循环链表者,可能开始想到的方法就是使用双重循环。当外层循环步进一个节点时,内层循环就遍历外层循环那节点之后的所有节点,然后比较内外循环的两个节点。若有节点地址相等,则表明该单链表是有循环的,反之则不存在循环。这种方法无疑效率比较低。

       而快慢指针应用于这个场景效率会明显提高。就像生活中的一个场景:一些人绕着环形跑道跑步,有的人快点,有的人慢点,过了一段时间会发现快的人又经过慢的人身旁,这就是循环跑。那么如果是理想直线跑道的话,两个人便不会相遇了,就没有绕圈即循环的性质。

       快慢指针的思想就是这样。快指针每次步进多个结点(视情况而定),慢指针每次只步进一个节点。那么如果该链表存在循环的话,快指针一定会再次碰到慢指针,反之则不存在循环。

代码示例:

例如长度为8,从1开始:
123456781
135713571
注:还有可能不直接是一个环,而是部分有环。下面会说到如何找环的入口点。2.在有序链表中寻找中位数

       该方法在不借助计数器变量的情况下,实现寻找中位数的功能。原理是:快指针的移动速度若是慢指针的2倍,当快指针到达链表尾部时,慢指针到达中点。可以想到尾部和中点的情况和节点数的奇偶有关。例如移动次数若为x,若1+2x到达了表尾,链表就有奇数个节点,此时慢指针为1+x,直接返回慢指针指向的数据即可。如果快指针指向倒数第二个节点,说明链表节点数为偶数,这时可以根据“规则”返回上中位数(1+x内容),下中位数(1+x+1内容),或者上下的平均数。

代码示例:

3.如果链表存在环,怎么找到环的入口点呢?       有一个单链表,其中可能有一个环,也就是某个节点的next指向的是链表中在它之前的节点,这样在链表的尾部形成环。       那么问题来了,如何判断一个链表是这类链表呢?即如果链表存在环,怎么找到入口点呢?      ① 如果循环方式为上图所示,即尾部有循环,当fast(两倍速)与slow相遇时,slow一定没有走完链表。      ②如果循环入口点为头结点,如上面表格情况,那么slow恰好遍历一圈。       对于第一种情况(如上图),我们从链表头A点与相遇点P点分别设置一个指针,每次各走一步,两个指针必定相遇(一定存在循环啦),且第一次相遇点就是环的入口了。       解释:A点为出发点,fast和slow在p点相遇,所以A->B->P 步数等于P->B->P  所以A->B等于P->B 那么如果在A点和p点分别设置一个指针,每次各走一步,两个指针就会在B点相遇,即相遇在环的入口处。        对于第二种情况,相遇点即链表头,也就是环的入口了。代码示例:       4.扩展问题       判断两个单链表是否相交,如果相交,给出相交的第一个点(两个链表都不存在环)。比较好的两个方法:       ①将其中一个链表首尾相连,检测另外一个链表是否存在环,如果存在,则两个链表相交,而检测出来的第一个入口即为相交的第一个点。       ②如果两个链表相交,两个链表从相交点到链表结束都是相同的节点,我们可以先遍历一个链表吗,直到尾部,再遍历另外一个链表,如果也可以走到同样的结尾点,则两个链表相交。         这时我们记下两个链表length,再遍历一次,长链表节点先出发前进lengthMax-lengthMin步,之后两个链表同时前进,每次一步,相遇的第一点即为两个链表相交的第一个点。参考文章:http://www.cnblogs.com/hxsyl/p/4395794.html#top                  百度百科   


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表