【2021/5/20 刷题笔记】相交链表以及双指针法

2021/6/5 - 更新
2021/5/20 - 初写


文章目录

  • 相交链表
    • 【题目】
    • 【我的方法】
    • 执行结果:
    • 【2021/6/5 更新】
  • 双指针法
    • 解题思路:
    • 复杂度分析:
    • 参考代码
      • python的三目运算符 x = c if a else b



相交链表

【题目】

编写一个程序,找到两个单链表相交的起始节点。 如下面的两个链表:
【2021/5/20 刷题笔记】相交链表以及双指针法_第1张图片
在节点 c1 开始相交。


注意:

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


来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/intersection-of-two-linked-lists
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

【我的方法】

相交意味着共用后面的链表,因此直接从后面相同的长度的节点开始比较。

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

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        a=headA
        b=headB
        n=0
        while(a and b):
            a=a.next
            b=b.next
        if(a):
            while(a):
                a=a.next
                n+=1
            b=headA
            a=headB
        else:
            while(b):
                b=b.next
                n+=1
            a=headA
            b=headB
        while(n>0):
            b=b.next
            n-=1
        while(a):
            if a==b:
                return a
            a=a.next
            b=b.next
        return a

执行结果:

  • 执行用时:176 ms, 在所有 Python3 提交中击败了47.61%的用户

  • 内存消耗:29.6 MB, 在所有 Python3 提交中击败了56.89%的用户

【2021/6/5 更新】

同样的思路,但代码上有所优化:

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        a=headA
        b=headB
        while(a.next!=None and b.next!=None):
            a=a.next
            b=b.next
        while(a.next!=None):
            a=a.next
            headA=headA.next
        while(b.next!=None):
            b=b.next
            headB=headB.next
        # print(headA)
        # print(headB)
        while(headA!=None):
            if headA==headB:
                return headB
            headB=headB.next
            headA=headA.next
        return None
# 执行用时:152 ms, 在所有 Python3 提交中击败了97.29%的用户
# 内存消耗:29.3 MB, 在所有 Python3 提交中击败了98.50%的用户

双指针法

解题思路:

设「第一个公共节点」为 node ,「链表 headA」的节点数量为 a ,「链表 headB」的节点数量为 b ,「两链表的公共尾部」的节点数量为 cc,则有:

  • 头节点 headA 到 node 前,共有 a - c 个节点;
  • 头节点 headB 到 node 前,共有 b - c 个节点;
    【2021/5/20 刷题笔记】相交链表以及双指针法_第2张图片

考虑构建两个节点指针 A​ , B 分别指向两链表头节点 headA , headB ,做如下操作:

  • 指针 A 先遍历完链表 headA ,再开始遍历链表 headB ,当走到 node 时,共走步数为:
    a + (b - c)

  • 指针 B 先遍历完链表 headB ,再开始遍历链表 headA ,当走到 node 时,共走步数为:
    b + (a - c)

如下式所示,此时指针 A , B 重合,并有两种情况:

a + (b - c) = b + (a - c)

  • 若两链表 有 公共尾部 (即 c > 0 ) :指针 A , B 同时指向「第一个公共节点」node 。
  • 若两链表 无 公共尾部 (即 c = 0 ) :指针 A , B 同时指向 null 。

因此返回 A 即可。

复杂度分析:

  • 时间复杂度 O(a + b) : 最差情况下(即 |a - b| = 1 , c = 0),此时需遍历 a + b个节点。
  • 空间复杂度 O(1) : 节点指针 A , B 使用常数大小的额外空间。

参考代码

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

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        a=headA
        b=headB
        while(a!=b):
            a=a.next if a else headB
            b=b.next if b else headA
        return a
  • python的三目运算符 x = c if a else b

    #等价于:
    #当 a = True , x =c 
    #当 a = False , x = b
    if a :
    	x = c
    else:
    	x = b
    


【部分内容参考自】

    1. 相交链表(双指针,清晰图解):https://leetcode-cn.com/problems/intersection-of-two-linked-lists/solution/intersection-of-two-linked-lists-shuang-zhi-zhen-l/

你可能感兴趣的:(刷题笔记,指针,数据结构,算法,链表,leetcode)