• 打败算法 —— 相交链表


    本文参考

    出自LeetCode上的题库 —— 相交链表,根据官方的双指针解法,本文从另一个角度进行分析

    https://leetcode-cn.com/problems/intersection-of-two-linked-lists/

    相交链表问题

    给定两个单链表的头节点 headA 和 headB ,找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null

    示例1:
    输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,6,1,8,4,5], skipA = 2, skipB = 3
    输出:Intersected at '8'

    示例 2:
    输入:intersectVal= 2, listA = [1,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
    输出:Intersected at '2'

    示例 3:
    输入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
    输出:null

    解题思路

    到目前为止已经做了很多双指针的解法,就不考虑遍历一遍链表,把结点存到链表里再进行判断的普通做法了。官方提供的双指针解法很巧妙,假设链表A比链表B长,那么两条链表的指针同时开始移动时,链表B的指针会率先到达链表的末尾。此时,链表B的指针下一步从链表A的起始位置移动,同理链表A的指针到达链表末尾后,下一步从链表B的起始位置移动。这种做法的本质,类似于填补上了两条链表长度上的差值。

    因此,可以有另一种思考方式,仍然假设链表A比链表B长,链表B的指针到达末尾后,计算链表A的指针还需要走多少步才会到达末尾,得到计数值cnt。然后两个链表再从头开始遍历,只不过链表A的指针要提前走好cnt个步数,相当于两个链表的指针从距离相交结点相同距离的起点出发,若相交结点存在,则一定能够相遇。

    双指针解法

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

    class
    Solution:
      def get_intersection_node(self, headA: ListNode, headB: ListNode) -> ListNode:
        if not (headA and headB):
          return None

        curr_a = headA
        curr_b = headB

        # 让较长的一个链表首先到达末尾 

        while curr_a and curr_b:
          if curr_a == curr_b:
            return curr_a
          curr_a = curr_a.next
          curr_b = curr_b.next

        cnt = 0
        if curr_a:
          # 链表较长,计算 a 比 b 长多少 

          while curr_a:
            curr_a = curr_a.next
            cnt += 1
          # 重新从头开始,让 a 事先走比 b 多出来的步数 

          curr_a = headA
          curr_b = headB
          while cnt:
            curr_a = curr_a.next
            cnt -= 1
        elif curr_b:
          # 链表较长,计算 b 比 a 长多少 

          while curr_b:
            curr_b = curr_b.next
            cnt += 1
          # 重新从头开始,让 b 事先走比 a 多出来的步数 

          curr_a = headA
          curr_b = headB
          while cnt:
            curr_b = curr_b.next
            cnt -= 1
        else:
          # 两个链表一样长,但是没有相交的结点 

          return None

        # 补充多余步数后,一起开始移动 

        while curr_a != curr_b:
          curr_a = curr_a.next
          curr_b = curr_b.next

        if curr_a:
          return curr_a
        else:
          return None

  • 相关阅读:
    Linux上天之路(十七)之Shell编程二
    Linux上天之路(十六)之Shell编程一
    Linux上天之路(十五)之文件查找
    Elasticsearch搜索调优权威指南 (1/3)
    【大数据】SparkSql 连接查询中的谓词下推处理 (二)
    【大数据】SparkSql 连接查询中的谓词下推处理 (一)
    搜索和其他机器学习问题有什么不同?
    Searching with Deep Learning 深度学习的搜索应用
    翻译 | The Principles of OOD 面向对象设计原则
    400+节点的 Elasticsearch 集群运维
  • 原文地址:https://www.cnblogs.com/kuluo/p/15970494.html
Copyright © 2020-2023  润新知