链表的相交与环问题

1.给出两个单链表的头指针,判断两个链表是否相交。假设这两个链表均不带环。示意图如下所示。


此道题目出现在编程之美中,在实际应用中确实存在需要判断两个链表是否相交的情况,比如在某些特殊时候,我们构造了一种数据结构,数据结构中两个链表是相交的,但是当我们想要释放一个链表中的所有节点时,也会也会释放掉另外一个链表中的部分节点,从而造成信息丢失,以后在访问另外一个链表的时候会出现意料之外的错误。

方法1.利用遍历地址的方法。对一个链表中的每个节点,判断其是否在另外一个链表中。时间复杂度为O(Length(list1)*Length(list2)),空间复杂度为O(1)。用两层while循环即可。

方法2.利用Hash的思想,对链表list1中的每个节点的地址进行hash排序,然后对list2中的每个节点的地址判断其是否在hash表中,这样的时间复杂度为O(max(Length(ist1)+Length(list2))),空间复杂度为O(Length(list1))。

方法3.判断处理之后的链表是否有环,也就是说我们可以将链表list1的最后一个节点指向第二个链表list2的头结点,如下图所示。然后我们发现如果从第二个链表list2的头结点出发一定可以回到头结点。当然判断完毕之后,一定要将链接去掉。


方法4.最后一个节点法。根据观察可以知道,如果两个不带环的链表相交于一个节点,那么这个节点及之后的节点都为两个链表所共有。所以我们可以遍历链表list1,保存指向最后一个节点的指针,然后遍历链表list2,找到最后一个节点,看两个指针是否相等,如果相等,则说明存在环。时间复杂度为O(Length(list1)+Length(list2)),空间复杂度为O(1)。

2.在题目1的情况下,如果有环,求两个链表相交的第一个节点的地址。

方法1.遍历链表1,长度为Length(list1),遍历链表2,长度为Length(list2)。假设Length(list1)>=Length(list2),则先遍历链表list1 Length(list1)-Length(list2)步,这个时候指向链表list1节点的指针和指向链表list2头结点的指针距离第一个相交节点的距离是一样的,同时移动两个指针的位置,直至两个指针相等。如下图所示。


方法2.将链表list1的尾节点的指针指向链表list2的头结点。设置两个快慢指针,一个指针每次向前走一步,一个每次向前走两步。相遇的时候,慢指针走了s步,快指针走了2s步,整个链表长为x,头指针距环的第一个节点的距离为L,环的长度为x-L,快慢指针相遇的节点距离环的第一个节点的距离为p。则存在如下等式:

s=L+p+n1*(x-L) // n1为慢指针在环中绕的次数 n1>=0

2s=L+p+n2*(x-L) //n2为快指针在环中绕的次数 n2>=1,快指针要想与慢指针相遇,绕的次数一定>=1,不然链表就不会存在环

两式相减得s=(n2-n1)*(x-L),可知L+p=(n2-2*n1)*(x-L),从此式可知假设在快慢指针相遇节点放一慢指针然后在链表头节点也放一个慢指针,则两个指针相遇的地方就是环的第一个节点。(看到别人对此类问题的解答,都说n1一定为0,换句话说快指针与慢指针相遇时,慢指针还没有遍历完整条链表,我想办法求证n1必定为0,但是却没有证明出来)

3.给出一个单向链表的头指针,判断是否存在环,如果存在环,给出环的第一个节点。

此问题与题目2的方法2是一实际上是一个问题,在此不多做赘述。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值