1.11判断两个无环单链表是否相交

Posted miao-study

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1.11判断两个无环单链表是否相交相关的知识,希望对你有一定的参考价值。

判断两个无环单链表是否交叉

题目描述:

技术图片
如上图,这两个链表相交于结点5,要求判断两个链表是否相交,如果相交,找出相交处的结点。

解题思路:

方法一:Hash 法

如上图所示,如果两个链表相交,那么它们一定会有公共的结点,由于结点的地址或引用可以作为结点的唯一标识,因此,可以通过判断两个链表中的结点是否有相同的地址或引用来判断链表是否相交。

方法二:首尾相接法

将这两个链表首尾相连(例如把链表headl尾结点链接到head2的头指针),然后检测这个链表是否存在环,如果存在,则两个链表相交,而环入口结点即为相交的结点。
技术图片

方法三:尾结点法

如果两个链表相交,那么两个链表从相交点到链表结束都是相同的结点,必然是Y字形,所以,判断两个链表的最后一个结点是不是相同即可。即先遍历一个链表,直到尾部,再遍历另外一个链表,如果也可以走到同样的结尾点,则两个链表相交,这时记下两个链衰的长度c1,c2,再遍历一次,长链表结点先出发前进|c1-c2|步,之后两个链表同时前进,每次一步,相遇的第一点即为两个链表相交的第一个点。

代码实现:

# -*-coding:utf-8-*- 
"""
@Author  : 图南
@Software: PyCharm
@Time    : 2019/9/7 21:24
"""


# 尾节点法
class Node:
    def __init__(self, data=None, next=None):
        self.data = data
        self.next = next


def printLink(head):
    if head is None or head.next is None:
        return
    cur = head.next
    while cur is not None:
        print(cur.data, end=' ')
        cur = cur.next
    print()

# 构造相交链表
def conInterLink(n1, n2, k):
    k = int(k)
    nums1 = list(map(int, n1.split(' ')))
    nums2 = list(map(int, n2.split(' ')))
    if len(nums1) > len(nums2):
        return conLink(nums1, nums2, k)
    else:
        head2, head1 = conLink(nums2, nums1, k)
        return head1, head2


def conLink(nums1, nums2, k):
    head1 = Node()
    head2 = Node()
    cur1 = head1
    cur2 = head2
    f = None
    for i in range(1, len(nums1) + 1):
        node = Node(nums1[i - 1])
        cur1.next = node
        cur1 = node
        if i == k:
            f = cur1
    for i in range(1, len(nums2) + 1):
        node = Node(nums2[i - 1])
        cur2.next = node
        cur2 = node
    cur2.next = f
    return head1, head2

# 遍历两个链表并计算长度
def traLink(head):
    cur = head.next
    count = 1
    while cur.next is not None:
        cur = cur.next
        count += 1
    return cur, count

# 长链表先走k步
def beforLink(head, k):
    cur = head.next
    for i in range(k):
        cur = cur.next
    return cur

# 获取相交点
def getPoint(head1, head2, count1, count2):
    cur1 = beforLink(head1, count1 - count2)
    cur2 = head2.next
    while cur1 is not None:
        if cur1 is cur2:
            return cur1.data
        cur1 = cur1.next
        cur2 = cur2.next


def findInterPoint(head1, head2):
    cur1, count1 = traLink(head1)
    cur2, count2 = traLink(head2)
    if cur1 is cur2:
        print("两个链表相交!")
        if count1 > count2:
            return getPoint(head1, head2, count1, count2)
        else:
            return getPoint(head2, head1, count2, count1)
    else:
        return "两个链表不相交!"

if __name__ == '__main__':
    n1 = input('Link1:')
    n2 = input('Link2:')
    k = input('相交点:')
    head1, head2 = conInterLink(n1, n2, k)
    printLink(head1)
    printLink(head2)
    print(findInterPoint(head1, head2))

运行结果:

链表一长度大于链表二:
技术图片
链表二长度大于链表一:
技术图片
两链表不相交:
技术图片
两链表相交在第一个节点:
技术图片

引申:如果单链表有环,如何判断两个链表是否相交

  1. 如果一个单链表有环,另外一个没环,那么它们肯定不相交。
  2. 如果两个单链表都有环并且相交,那么这两个链表一定共享这个环。如下图
    技术图片
  3. 判断两个有环的链表是否相交的方法为:首先找到链表headl中环的入口点pl,然后遍历链表head2,判断链表中是否包含结点 pl,如果包含,则这两个链表相交,否则不相交。
  4. 找相交点的方法为:把结点pl看作两个链表的尾结点,这样就可以把问题转换为求两个无环链表相交点的问题。

以上是关于1.11判断两个无环单链表是否相交的主要内容,如果未能解决你的问题,请参考以下文章

判断两条链表是否相交(公共部分)并找出相交处

算法总结之 两个单链表相交的一些列问题

9.判断两个单链表是否相交

判断两个单链表是否相交及相交的第一个节点

判断两个单链表是否相交?若相交求交点

判断两个单链表是否相交