LeetCode 160. Intersection of Two Linked Lists

题目

编写一个程序,找到两个单链表相交的起始节点。
如下面的两个链表:
在这里插入图片描述
在节点 c1 开始相交。

示例 1:

在这里插入图片描述

输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
输出:Reference of the node with value = 8
输入解释:相交节点的值为 8 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。

示例 2:

在这里插入图片描述

输入:intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
输出:Reference of the node with value = 2
输入解释:相交节点的值为 2 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [0,9,1,2,4],链表 B 为 [3,2,4]。在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。

示例 3:

在这里插入图片描述

输入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
输出:null
输入解释:从各自的表头开始算起,链表 A 为 [2,6,4],链表 B 为 [1,5]。由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。
解释:这两个链表不相交,因此返回 null。

注意:

  • 如果两个链表没有交点,返回 null.
  • 在返回结果后,两个链表仍须保持原有的结构。
  • 可假定整个链表结构中没有循环。
  • 程序尽量满足 O(n)
    时间复杂度,且仅用 O(1) 内存。

思路

这道题可以暴力搜索,也可以用哈希方法,但满足O(n)和O(1)的方法更佳。我自己没想到,看了Solution里的思路简直拍案叫绝。
设置两个指针pA和pB分别是headA和headB,分别让他们往后走,肯定有一个长一个短,有一个先走到头,假设是pA,那么都走到末尾pA比pB就少走几个节点,我们现在让pA指向headB继续走,pB走到末尾后指向headA继续走,如果有交点的话,pA和pB就一定会一起同时走到这个点,返回就可以了。
那么还有一些情况,比如两个一样长怎么办,我就多加了一个判断语句,判断第二个指针是否也在末尾。换头(pA指向headB)不应当直接链上,而应当赋值到开头节点,同时pB前进一步,否则改了第一个第二个就判断不了末尾了。对于两个单链表不想交的情况,我是判断他们末尾(abot,bbot)是否相等来实现,不等就说明到最后也没有相同的节点,那肯定是没交点了。最终时间超过70%已提交结果,空间超过90%已提交结果,具体实现如下:

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def getIntersectionNode(self, headA, headB):
        """
        :type head1, head1: ListNode
        :rtype: ListNode
        """
        #headA, headB = headB, headA
        pointerA = headA
        pointerB = headB
        if headA == headB:
            return headA
        if not headA or not headB:
            return None
        if not pointerA or not pointerB:
            return None
        while pointerA.next and pointerB.next:
            pointerA, pointerB = pointerA.next, pointerB.next
            if pointerA == pointerB:
                return pointerA
        if not pointerA.next:
            abot = pointerA.val
            if pointerB.next:
                pointerB = pointerB.next
                pointerA = headB
            while pointerB.next:
                pointerB = pointerB.next
                pointerA = pointerA.next
            bbot = pointerB.val
            pointerB = headA
            pointerA = pointerA.next
            if abot != bbot:
                return None
            while True:
                if pointerA == pointerB:
                    return pointerA
                else:
                    pointerA = pointerA.next
                    pointerB = pointerB.next
        if not pointerB.next:
            bbot = pointerB.val
            if pointerA.next:
                pointerA = pointerA.next
                pointerB = headA
            while pointerA.next:
                pointerA = pointerA.next
                pointerB = pointerB.next
            abot = pointerA.val
            pointerA = headB
            pointerB = pointerB.next
            if abot != bbot:
                return None
            while True:
                if pointerB == pointerA:
                    return pointerA
                else:
                    pointerB = pointerB.next
                    pointerA = pointerA.next

我这个代码显得很笨重,太蠢了,我看了看评论区里相同的思路的做法的代码,又惊了,先贴上来看看:

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None


class Solution:
    # @param two ListNodes
    # @return the intersected ListNode
    def getIntersectionNode(self, headA, headB):
        if headA is None or headB is None:
            return None

        pa = headA # 2 pointers
        pb = headB

        while pa is not pb:
            # if either pointer hits the end, switch head and continue the second traversal, 
            # if not hit the end, just move on to next
            pa = headB if pa is None else pa.next
            pb = headA if pb is None else pb.next

        return pa # only 2 ways to get out of the loop, they meet or the both hit the end=None

# the idea is if you switch head, the possible difference between length would be countered. 
# On the second traversal, they either hit or miss. 
# if they meet, pa or pb would be the node we are looking for, 
# if they didn't meet, they will hit the end at the same iteration, pa == pb == None, return either one of them is the same,None

代码写的及其简洁,但我想到的问题里面都有很巧妙地解决,精华就在于这两行代码:

pa = headB if pa is None else pa.next
pb = headA if pb is None else pb.next

这两行很完美的解决了先到之后换头和继续走的问题,并且如果两个没有交点的话,他们换头之后会同时走到终点然后基于while的条件而退出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值