avatar

目录
链表的快慢指针问题

求链表的中间值

list 中一般有 size 这个成员数属性,要求链表的中间值,只要遍历 size/2 次即可,但是如果没有这个 size 属性该如何求链表的中间值呢?

可以定义两个指针,开始都指向链表的头节点,然后慢指针每次移动一个节点,快指针每次移动两个节点,当快指针移动到元素末尾时,慢指针刚好指向链表的中间。

快慢指针求链表中间值.png

原理: 快指针是慢指针的两倍,快指针走完时慢慢指针当然走了一半,这个很好理解

判断单向链表是否有环

可以定义两个指针,开始都指向链表的头节点,然后慢指针每次移动一个节点,快指针每次移动两个节点,如果快慢指针会相遇则说明单链表有环

判断单向链表是否有环.png

原理:
两个人绕圈跑,快的人一定会追上慢的人,且至多追一圈的距离(追一圈的距离等于快指针跑两圈,慢指针跑一圈,也就是两人一旦都在圈内,从此时开始算,快的最多还需要跑两圈就一定能遇到慢的)

为什么不会“错过”?

因为快指针每次走两步,慢指针每次走一步,也就是快指针和慢指针每次走相差步数是1,当两指针都在环内时,快指针每次都能追上慢指针1步,迟早会追上。如果步迈相差 不是1 那才可能会“错过”。

那快指针至少和至多追多少次能追上慢指针呢?

四种情况: 这里 n = 1,2,3 …

  • 快指针走完所有节点后第 n 次走到或走过环的连接点时,慢指针还没进入环(走到或走过连接点)
    那快指针继续走,等到慢指针进入环后(走到或走过连接点)才开始追
  • 快指针走完所有节点后第 n 次走到或走过环的连接点时,慢指针已进入环了(走到或走过连接点),且刚好和快指针相遇(可能在环的任何位置)
    那此时就不用追了,即 0 次
  • 快指针走完所有节点后第 n 次走到或走过环的连接点时,慢指针已进入环了(走过或走到连接点),且此时慢指针刚好在快指针后一节点,那就要追 环的长度-1 次
  • 特殊情况:一开始快指针和慢指针都在环内(循环链表),快指针走完所有节点后第 1 次走到或走过环的连接点时,慢指针在环的中间位置,此时要追 环的长度/2 次

结论:两指针都进入环后,至少一次都不用追,至多追 环的长度-1 次。

求有环单链表的环长

从第一次相遇后开始,再次相遇时慢指针走过的步数就是环的长度。

原理:
两人步迈相差两倍,同时从环内某点出发,再次相遇时,快的走了2圈,慢的走了1圈,想要求环的长度,也就刚好是慢指针走过的长度,请结合上面快指针追慢指针的第二种情况和第三种情况理解。

求单链表有环时的连接点

相遇后,慢指针从相遇点出发,再设一个慢指针从头节点出发,当两慢指针再相遇时的那个点就是连接点。

原理:相遇点正向到连接点的距离 = 头指针到连接点的距离,推导如下

单链表有环求连接点.png

求单链表有环时的总长度

链表总长度 = 环的长度 + 头节点到环的连接点的距离(包含头节点不包含连接点)

文章作者: Juchia Lu
文章链接: https://juchia.com/2018/11/12/%E9%93%BE%E8%A1%A8%E7%9A%84%E5%BF%AB%E6%85%A2%E6%8C%87%E9%92%88%E9%97%AE%E9%A2%98/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Juchia