python数据结构,快慢指针

最近听的b站左程云数据结构,记录下来题和代码,python实现

    • 链表
      • 快慢指针
        • 题目1:返回链表的第一个环结点,没有环就返回空
        • 题目2:判断两个链表有没有共同结点,返回第一个共同结点,在没有环的情况下
        • 题目3:两个链表有环的情况下,返回第一个相交结点

b站视频链接

链表

快慢指针

  • 目的:用于判断一个链表中有没有环
  • 使用:
    快慢指针一开始都在头结点
    快指针每次走2步
    慢指针每次走1步
    在第一次快慢指针相遇时,快指针回到头结点,并且之后,每次走1步,慢指针继续。
  • 结果:
    在他俩第二次相遇时候,一定是环的第一个结点
  • 例子:
题目1:返回链表的第一个环结点,没有环就返回空

代码

def getLoopNode(head):
    if not (head and head.next and head.next.next):     # 只要有一个为空就返回空
        return None
    n1 = head.next          # 慢指针
    n2 = head.next.next     # 快指针
    while n1 != n2:
        if n2.next == None or n2.next.next == None:
            return None
        n2 = n2.next.next
        n1 = n1.next
    n2 = head       # n2快指针回到开头
    while n1 != n2:
        n1 = n1.next
        n2 = n2.next
    return n1
题目2:判断两个链表有没有共同结点,返回第一个共同结点,在没有环的情况下
  • 来源 leetcode160题
  • 分析:如果两个链表相交,那一定是呈现Y字型,因为结点之后一个next后指针,不可能指向多个
  • 实现:
    1)两个各遍历一遍,计算长度,和保存两个最后的end1和end2结点
    2)如果尾指针不相同,那么一定不相交
    3)尾指针相同的情况下,长的链表先走和短的链表差值步,达到同一起跑线
    4)从同一起跑线,每次各走1步,那么相遇的第一个点,就是共同结点
    5)时间复杂度O(n),空间复杂度O(1)
  • 代码
def noLoop(head1,head2):
    if head1 == None or head2 == None:
        return None
    cur1,cur2,n = head1,head2,0   # 两个指针和一个记录长度的n
    while cur1.next:
        n += 1
        cur1 = cur1.next
    while cur2.next:
        n -= 1
        cur2 = cur2.next            # n此时记录的是len1 - len2
    if cur1 != cur2:
        return None
    cur1 = head1 if n >0 else head2             # cur1 保存长链表的头指针
    cur2 = head2 if cur1 == head1 else head2    # cur2 保存短链表的头指针
    for i in range(abs(n)):                     # 长链表先走n步
        cur1 = cur1.next
    while cur1 != cur2:
        cur1 = cur1.next
        cur2 = cur2.next
    return cur1
题目3:两个链表有环的情况下,返回第一个相交结点
  • 分析:
    有环的情况,只有三种
    python数据结构,快慢指针_第1张图片

  • 针对这三种情况,画了算法流程图,方便理解
    python数据结构,快慢指针_第2张图片

def bothLoop(head1,loop1,head2,loop2):
    if loop1 != loop2:          # 两个环的第一个入环结点不一样,用loop1和loop2作为中止结点,和无环结点一样的代码
        cur1,cur2,n = head1,head2,0
        while cur1 != loop1:                # 以loop1为中止结点
            n +=1
            cur1 = cur1.next
        while cur2 != loop2:                # 以loop2为中止结点
            n -= 1
            cur2 = cur2.next
        cur1 = head1 if n > 0 else head2             # cur1 保存长链表的头指针
        cur2 = head2 if cur1 == head1 else head2    # cur2 保存短链表的头指针
        for i in range(abs(n)):
            cur1 = cur1.next
        while cur1 != cur2:
            cur1 = cur1.next
            cur2 = cur2.next
        return cur1
    else:                       # 两个环入环结点一样,外星人形状
        cur1 = loop1.next
        while cur1 != loop1:    # 保持一个不动,另一个循环
            if cur1 == loop2:
                return loop1    # 相遇就返回
            cur1 = cur1.next
        return None                     # 不相遇就不相交

def getIntersectNode(head1,head2):
    if head1 == None or head2 == None:
        return None
    loop1 = getLoopNode(head1)
    loop2 = getLoopNode(head2)
    if loop1 == None and loop2 == None:
        return noLoop(head1,head2)          # 两个链表都没有环
    elif loop1 and loop2:                   # 两个链表都有环
        return bothLoop(head1,loop1,head2,loop2)
    else: return None                       # 不存在其他情况

你可能感兴趣的:(python算法题,数据结构,链表,算法,python)