160. 相交链表(Python)

Python027

160. 相交链表(Python),第1张

难度:★★☆☆☆

类型:链表

编写一个程序,找到两个单链表相交的起始节点

如下面的两个链表:

在节点 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) 内存。

这道题与 【题目141. 环形链表】 属于同一题型,环形链表可以使用快慢指针判断,这里我们同样使用双指针进行判别,不过步长都是一步,让两个指针分别从两个链表头结点开始向后移动,当其中一个指针走到链表末尾后,换到另一个链表的头结点上,另一个指针也是如此,这样如果两个链表相交,则一定可以相遇,且根据数量关系可知,首次相遇的结点即为相交结点。

如有疑问或建议,欢迎评论区留言~

4

开始遍历此链表

15

14

13

12

链表遍历已经结束

None

开始遍历此链表

15

14

111

13

12

链表遍历已经结束

None

开始遍历此链表

111

15

14

111

13

12

链表遍历已经结束

None

开始遍历此链表

111

111

15

14

111

13

12

链表遍历已经结束

None

楼主你好!

看你的代码存在很多问题,一个个来说明

1)首先你代码的报错源于你想用list来展开你的SLinkedList类,在python中,除非内置的可迭代对象外,其他都需要实现__iter__()函数,才能用list来进行展开。注意:判断一个对象是否可迭代,请使用isinstance(obj, Iterable)来判断obj是不是可以迭代,Iterable需要从collections中导入

2)插入的方法存在严重问题,按楼主的方法插入的话,因为头节点始终在变,所以当你需要遍历链表的时候就会找不到头节点;

3)pop的方法实现也有问题,因为是单向链,所以无法从末节点开始删除,只能删除头节点

4)top方法的意图未知

其他:

下面列举了一下我修改后的方案,做了一些锦上添花的操作,每个基本操作都会返回链表对象,这样就可以使用链式操作来写代码;迭代函数使用yield来实现,避免展开时占用不必要的内存。

另:我的展开时直接取链表中各个节点的元素,加了一些关键注释在代码中;

# -*- coding: utf-8 -*-

class Node:

    def __init__(self):

        '''

        elm:节点元素

        nxt:下个节点指针

        '''

        self.elm, self.nxt = None, None

        

class SLinkedList:

    def __init__(self):

        '''

       head: 链表头

       end_point: 链表尾

       '''

        self.head      = None

        self.end_point = None

    

    def push(self, x):

        p = Node()

        p.elm = x

        if self.head is None:

            self.head      = p

            self.end_point = p

            return self

        self.end_point.nxt = p

        self.end_point     = p

        return self

    

    def pop(self):

        '''因为实现的是一个单链表,所以只能从头开始删除节点'''

        if self.head.nxt is None:

            return

        self.head = self.head.nxt

        return self

    

    def __iter__(self):

        temp_node = self.head

        while temp_node is not None:

            yield temp_node.elm

            temp_node = temp_node.nxt

        

        

if __name__ == '__main__':

    '''增加1,2,5三个元素,并删除一个头节点'''

    mylinklist = SLinkedList().push(1).push(2).push(5).pop()

    print(list(mylinklist))

其实python这个语言使用链表有些画蛇添足,但是如果拿来当作需求练手也无妨。

望采纳,谢谢!