Leetcode 关于twopointers的题解思路


最近在刷leetcode熟悉一些常用的算法知识,刷完了Two Pointers的大部分easy, medium 的题目,在这里做一些总结,一来方便自己以后可以回看,又可以与大家分享自己的一点小小的心得。笔者用的语言是python, 作为解释性语言,对于追求效率的新手来说,非常适合入门(来自西南某高校的我第一门接触到语言),闲话不多说,我们开始走进Two pointers的套路。


Linked List Cycle(141,142)

题目的大概意思是:
141:一个链表有没有一个“环”(easy)
142:这个环的起点是哪个节点(medium)

对于是否是环,我们运用常用的 slow_pointer 和 fast_pointer 可以在O(N)复杂度下解决该问题:
解决方案的主体是一个循环,slow_pointet的速度为1,fast_pointer的速度为2, 如果存在“环” ,这两个pointer总会在某一点相遇;如果不存在“环”,fast_pointer就会因为到达链表的尾部而跳出循环。

def hasCycle(self, head):
    """
    :type head: ListNode
    :rtype: bool
    """
    if head is None : return False
    slow, fast = head, head
    while True:
        if fast.next == None: return False
        if fast.next.next == None: return False
        slow, fast = slow.next, fast.next.next
        if slow is fast: return True

下一个问题就是如何找到环起点的位置。我的思路很直接,也就是延续上一问题,首先改动原代码如下:

    if head is None: return None
    slow, fast = head, head
    while True:
        if fast.next == None: return None
        if fast.next.next == None: return None
        slow, fast = slow.next, fast.next.next
        if slow is fast: break

此时,我们先找到环的大小,思路是当环内一个pointer以1的速度移动,当返回到起点的时候,就知道了环的大小
因此我们新增一个tmp的pointer从head.next开始:

    tmp, fast= head.next, fast.next
    while not(fast is slow): tmp, fast= tmp.next, fast.next

此时head与tmp的距离也就是环的大小, 下面head与tmp同时以1的速度移动,当tmp与head重合的时候,这个重合点也就是环的起点。

    while not(head is tmp): tmp, head= tmp.next, head.next

因此完整的代码是:

def detectCycle(self, head):
    """
    :type head: ListNode
    :rtype: ListNode
    """
    if head is None: return None
    slow, fast = head, head
    while True:
        if fast.next == None: return None
        if fast.next.next == None: return None
        slow, fast = slow.next, fast.next.next
        if slow is fast: break
    
    tmp, fast= head.next, fast.next
    while not(fast is slow): tmp, fast= tmp.next, fast.next
    while not(head is tmp): tmp, head= tmp.next, head.next
    return head

未完待续......

你可能感兴趣的:(Leetcode 关于twopointers的题解思路)