环形链表,链表中的尾节点指向链表中的某个节点导致形成循环的链表。
通过图可以这样表示。
我们一般采用快慢指针的方式解决带环链表的题目,下面直接上例题
环形链表
力扣链接:
. - 力扣(LeetCode)
让我们判断一个链表是否为环形链表。
思路:
如果不是循环链表,最终会指向NULL
而如果是循环链表
1.快指针会比慢指针先进入环形链表。
2.快指针速度会比慢指针快一个单位,因此两个指针每次移动都会拉近一个距离。
3.当两个指针相等时,说明是环形链表。
参考代码:
思考:
若快指针速度为2,3,甚至n时,能否解决该问题。
其实这是一个数学问题
假设快指针速度为n。
快指针进入循环后需要追击慢指针的长度为m
循环长度为C
慢指针遇到快指针时的运动长度为L
以上参数均为整数
那么我们可以写出以下式子:
nL=L+x*C+C-m (x为快指针进入循坏时的运动圈数,大于0)
(n-1)L=(x+1)*C-m
L=[(x+1)*C-m]/(n-1)
其中(C为固定的,x可以取任何大于0的值,L,m均为整数),实现该条件即可
n为2即快指针速度为2时可以满足所有的情况
以n=3为例子
需要(x+1)*C-m为偶数
当C为奇数时,由于x+1可以为任意值,所以(x+1)*C既可以为奇数也可以为偶数,无论m为何值均可均成立
当C为偶数时,(x+1)*C只能为偶数,那么m则必须为偶数才能成立。
随机链表的复制
力扣链接:
. - 力扣(LeetCode)
思路:
我们可以在原先每个节点之后都创建上一个新节点并与原链表串起来
那么如果random指向NULL则原节点的后一个位置即为我们创建的对应的节点,这个节点的random也指向NULL
如果原节点不指向NULL,则指向原节点的random节点的下一个位置(即我们创建的与该节点对应的节点)
串完之后将我们创建好的链表从中取出即可
参考代码:
环形链表2
力扣链接
. - 力扣(LeetCode)
思路:
这道题也是一个数学问题
我们假设:
头节点到循环的起始位置之间的距离为a
相遇位置到起始位置的距离为b
起始位置到相遇位置的距离为c
慢指针速度为1
快指针速度为2
那么慢指针到相遇位置移动长度为slow=a+ib+c
快指针到相遇位置移动长度为fast=a+jb+c
那么fast=2*slow
即a+jb+c=2*(a+ib+c)
即c=(j-2i)b-a
我们可知相遇位置只要再移动a个单位即可到达循坏位置开始的(j-3i)b位置,即起始位置
那么我们就让头节点和慢指针一起移动,头节点和慢指针移动a个单位后均会到达起始位置,也就是相遇