两个链表的第一个公共结点

题目描述

输入两个无环的单链表,找出它们的第一个公共结点。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)

解题思路

  1. 如图:对于长短不一致的两个链表pHead1、pHead2,使用双指针temp1=pHead1、temp2=pHead2,同时进行循环遍历,短的链表pHead1必定先走到None,这时让短链表的指针继续从长的链表的头结点开始继续遍历;紧接着当长链表pHead2也走到None时,继续从短链表的头结点继续遍历,这样两个指针所遍历的链表长度相等,即为长链表与短链表的长度之和,遍历直到两个指针的指向相同时,表示当前指针所指向结点为第一个公共结点,返回任意指针指向即可。
    在这里插入图片描述
  2. 循环遍历指针往下走,直到有一个指针为空,说明该指针指向链表是短的那个;
    知道了短链表,可以计算长短链表的长度差;
    如果temp1不为空,temp2为空,短链表是pHead2,计算长链表pHead1走多少步到None,步数即为两个链表的长度差;
    此时计算出了k值即为两链表的长度差,这时将两个指针重新指向两链表的首结点,从头开始遍历,这时为了让链表步伐一致,我们让长链表指针先移动k步,然后两个指针同时移动,直到两个指针所指向的结点相同时,说明找到了公共结点,遍历停止;
    temp2不为空,temp1为空的情况,说明temp1是短链表与前面一致。
    在这里插入图片描述

代码示例

# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

#
# 
# @param pHead1 ListNode类 
# @param pHead2 ListNode类 
# @return ListNode类
#
class Solution:
    def FindFirstCommonNode(self , pHead1 , pHead2 ):
        # write code here
        temp1 = pHead1
        temp2 = pHead2
        while temp1 != temp2:
            # temp1不为空,继续走
            if temp1:
                temp1 = temp1.next
            # temp1为空,temp1短,则temp1从pHead2的头接着开始走
            else:
                temp1 = pHead2
            # temp2不为空,继续走
            if temp2:
                temp2 = temp2.next
            # temp2为空,temp2短,则temp2从pHead1的头接着开始走
            else:
                temp2 = pHead1
        return temp1

    def FindFirstCommonNod2(self, pHead1, pHead2):
        # write code here
        temp1 = pHead1
        temp2 = pHead2

        while temp1 and temp2:
            if temp1 == temp2:
                return temp1
            temp1 = temp1.next
            temp2 = temp2.next
            
        temp1 = pHead1
        temp2 = pHead2
        # 循环遍历指针往下走,直到有一个指针为空,
        # 说明该指针指向链表是短的那个
        while temp1 and temp2:
            # 考虑边界条件,只有一个链表,
            # 没有公共结点的情况({},{},{1,2,3,4})
            if temp1 == temp2:
                return temp1
            temp1 = temp1.next
            temp2 = temp2.next

        # 知道了短链表,可以计算长短链表的长度差
        # 如果temp1不为空,temp2为空,短链表是pHead2
        # 计算长链表pHead1走多少步到None,步数即为两个链表的长度差
        if temp1:
            k = 0
            temp1 = temp1.next
            k += 1

        # 此时计算出了k值即为两链表的长度差
        # 这时将两个指针重新指向两链表的首结点,从头开始遍历
        # 这时为了让链表步伐一致,我们让长链表指针先移动k步,
        # 然后两个指针同时移动,直到两个指针所指向的结点相同时,说明找到了公共结点,遍历停止
        temp1 = pHead1  # 长
        temp2 = pHead2  # 短
        for i in range(k):
            temp1 = temp1.next
        while temp1 != temp2:
            temp1 = temp1.next
            temp2 = temp2.next
        return temp1
        # temp2不为空,temp1为空的情况,说明temp1是短链表
        if temp2:
            k = 0
            temp2 = temp2.next
            k += 1

        temp1 = pHead1
        temp2 = pHead2
        for i in range(k):
            temp2 = temp2.next
        while temp1 != temp2:
            temp1 = temp1.next
            temp2 = temp2.next
        return temp1

上述代码可以将if判断条件后的代码块进行封装,然后分别调用

    def FindFirstCommonNod2(self, pHead1, pHead2):
        # write code here
        temp1 = pHead1
        temp2 = pHead2

        while temp1 and temp2:
            if temp1 == temp2:
                return temp1
            temp1 = temp1.next
            temp2 = temp2.next

        def findShort(shortPointer, longPointer, shortHead, longHead):
            k = 0
            while longPointer:
                longPointer = longPointer.next
                k += 1
            shortPointer = shortHead
            longPointer = longHead
            for i in range(k):
                longPointer = longPointer.next
            while shortPointer != longPointer:
                shortPointer = shortPointer.next
                longPointer = longPointer.next
            return shortPointer

        if temp1:
            return findShort(temp2, temp1, pHead2, pHead1)
        if temp2:
            return findShort(temp1, temp2, pHead1, pHead2)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值