数据结构1-2. 链表中的双指针

经典问题:判断一个链表是否有环。

可以使用哈希表来解决该问题,即将链表每个结点的指针存入哈希表,出现重复的地址即说明链表中存在环。

python代码如下  时间复杂度O(N)  空间复杂度O(N)

def hasCycle(head):
    cur = head
    if cur is None:
        return False
    
    hash1 = set()
    hash1.add(cur)
    while cur.next is not None:
        cur = cur.next
        if cur in hash1:
            return True
        hash1.add(cur)
    return False

但是,使用双指针是一个更加有效的方案,通过设定步长不同的两个快慢指针,对链表进行遍历,会有以下两种情况:

  • 如果没有环,快指针将停在链表的末尾
  • 如果有环,快指针会与慢指针相遇

比较安全的选择是慢指针每次走一步,快指针每次走两步,快指针比慢指针每次多一步,这样对于长度为M的链表,在经过M次迭代后,快指针一定能与慢指针相遇。

python代码如下  时间复杂度O(N)  空间复杂度O(1)

class Solution(object):
    def hasCycle(head):
        """
        :type head: ListNode
        :rtype: bool
        """
        slow = head
        fast = head

        while fast is not None and fast.next is not None and fast.next.next is not None:
            slow = slow.next
            fast = fast.next.next
            if slow == fast:
                return True
        return False

如果问题限制结点数量,甚至可以循环,当超过结点数量时说明有环  0 0

问题2:如果链表存在环,找到入环的结点

同理,哈希表会很简单,但是空间复杂度是O(N),python代码如下

def hasCycle(head):
    cur = head
    if cur is None:
        return False
    
    hash1 = set()
    hash1.add(cur)
    while cur.next is not None:
        cur = cur.next
        if cur in hash1:
            return cur
        hash1.add(cur)
    return False

也可用快慢指针来实现找入环的结点,如图所示

   

 

对于上图所示的链表,慢指针每次走一步,走过的距离为 D + S1 ,快指针每次走两步,走过的距离为 n * (S1 + S2) + D,快指针走的路程为慢指针的2倍,则有

    2 * (D + S1) = n * (S1 + S2) + D

整理得   D = ( n - 1) * ( s1 + s2 ) + s2

即起始点到入环点得距离与首次相遇点绕环 ( n - 1 ) 圈后再回到入环点得距离相同。

双指针找入环点:快慢指针找到环内首次相遇点后,从起始点和首次相遇点每次前进一,再次相遇的点就是入环点。

python代码如下

def findInputCycle(head):
    slow = head
    fast = head
    while fast is not None and fast.next is not None and fast.next.next is not None:
        slow = slow.next
        fast = fast.next.next
        if slow == fast:
            con = fast
            slow = head
            while con != slow:
                slow = slow.next
                con = con.next
            return con
    return None

 

posted @ 2022-07-01 16:44  Liang-ml  阅读(58)  评论(0)    收藏  举报