关于单链表在使用中产生的常见问题

如何判断链表是否带环

简单科普一下什么是带环链表,正常的单链表结构是线性的,他的最后一个节点指向的是空,带环则是最后一个节点指向前面的某一个节点,形成一个环形,比较经典的就是约瑟夫问题,它就是一个带环链表,而我们想要判断它是否是带环链表,需要用到我们的快慢指针。

假设带环链表是这样的,在进入环之前我们称之为L ,而环我们称之为C,使用快慢指针,快指针一次走两步,慢指针一次走一步,这样它们在某一次就会相等,就可以证明这个链表是带环的,否则就是不带环的, 根据上图数据我们得出公式 2L = L+x*C+C-N,经过化简得到L = x*C+C-N。

而由于fast走的快,所以一定先进环,当slow到达环节点时,fast至少已经走了x*C+C-N圈

且x至少为1,此时fast和slow的距离就是N,这种情况下在一定的圈数内fast就能追上slow证明是带环链表。

此时我们又会产生一些问题,fast走两步能找到slow,那走三步,四步以及更多步还能不能找到。

这样我们需要分情况来讨论,此时slow还是走一步,但是fast走三步,公式也没多大变化,化简一下得到2L = (x+1)*C-N 。

也就是N的距离每次会缩减2 那么如果N是偶数的情况下,一直-2是会等于0,也就是说一圈就能证明是否带环,而如果N是奇数,那么-2下来最后会等于-1,也就是C-1, 代表这一轮错过了。

而C-1又可以分两种情况讨论,如果C-1是偶数,那么皆大欢喜,这轮可以证明,但是如果还是奇数,那么寄,死循环了,永远无法证明。

最后我们得出结论N是偶数的话,第一圈就追上了,而如果N是奇数,那么第一轮追不上要看C-1,如果C-1是偶数那还能追上,如果C-1是奇数,那就陷入死循环追不上了。但是我们根据公式来看,这追不上的情况其实是不可能出现的,因为要出现这种情况N是奇数且C是偶数才行,而N如果是偶数则没有C的事,N是奇数,那么C不可能是偶数,因为根据公式2L = (x+1)*C-N ,可以反证,偶数=偶数-奇数,这是不可能成立的,所以一定可以追上,只是走几轮的问题。fast走其他步数的情况和走三步大同小异,这里就不一一说明了。具现到题目上写代码其实不难,难的是总结出公式来推导。题目及代码如下

若带环如何找到环

经过上面,我们会了如何判断带环,那么我们继续深入,学习如何找到换节点。

首先我们想要找到环,得先确认它是带环链表,所以前面先照搬上面的操作,利用快慢指针得出相遇的点,我们需要明白此时fast指针肯定不会超过一圈,因为超过一圈,就找到了,所以如图

此时,其实代码逻辑已经出来了,假设x为1圈,那么L=C-N,C-N就是相遇点到环节点的长度,而C-N到达环节点时L也会到达,恰到好处的得到了环节点,而如果x不为1,其实没有区别,因为走完一个完整的环还会回到原点,影响它的只会是C-N,最终都会等于L。

题目及代码如图

但是如果我们想不到这一步,没法总结个公式然后想出代码,也可以找到slow和fast相遇的点,把它的next记录一下再置为空,形成一个断点,这样问题就变成求两个链表的相交处了,问题就简单一点了,但是代码多了一些。

随机链表的复制

这个是什么意思呢,其实很简单,就是把一个单链表复制一份,成为一个新的单链表,不过这个单链表除了next还有一个指向随机节点的指针,要求这个指针也只想拷贝出来的新节点,这导致我们不能真的直接复制一份这个单链表,还需要考虑怎么指向随机值的拷贝节点。

我提供的做法呢 是在每一个原节点后开辟一个原节点的拷贝尾插,这样就能确定随机值该怎么指向。

这样每一个节点后就有一个相同的自己,然后,我们在找到它指向的随机值,把随机值后面的拷贝链接到我们身上,这样重复下去我们的拷贝链表就出来了。

接下来我们只需要把拷贝的链表剥离出来就可以了。

这样就大功告成,这道题的难点就在于找到每一个random的地址,由于我们不能让random指向原链表的random,所以我们采取了拷贝的方法,让找到random和拷贝新链表的环节一起进行,利用每一个原节点的next都是它的拷贝,进而得出它的random的next也是它的拷贝,把它链接上就算完成了。

  • 10
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值