剑指offer23 链表中环的入口节点

这题可以分为两部分,首先判断是否有环,然后如果有环,寻找其入口节点。

自己开始的思路是,首先判断是否有环(快慢双指针),然后如果有环,以每个节点为假想入口节点,判断其是否是入口节点,但是这样时间复杂度O(n^2),略复杂。

然后参考剑指offer的思路:

1.判断是否有环

2.找到环的长度

3.设链表长度l,环长度n,设置两个指针p1,p2 , p1先走n步,则:

p1距离最后一个节点还有l-n的距离,即l-n步后,p1回到环入口节点

而p2距离环入口节点也是l-n步

故p1p2会在环入口节点相遇。

/*
 public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}
*/
public class Solution {

    public ListNode EntryNodeOfLoop(ListNode pHead)
    {
        ListNode fast = pHead,slow = pHead;
        while(fast!=null){
            fast=fast.next;
            if(fast!=null) fast=fast.next;
            else return null;//no loop
            slow = slow.next;
            if(fast==slow) break;
        }
        //break means there is loop
        //find the length of loop
        int loopLength = 1;
        fast = fast.next;
        while(slow!=fast){
            fast=fast.next;
            loopLength++;
        }
        //find the EntryNode
        fast=pHead;slow=pHead;
        for(int i=0;i<loopLength;i++){
            fast=fast.next;
        }
        while(slow!=fast){
            slow=slow.next;
            fast=fast.next;
        }
        return fast;
    }
}

运行时间:25ms

占用内存:9672k

# -*- coding:utf-8 -*-
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution:
    def EntryNodeOfLoop(self, pHead):
        # write code here
        if pHead is None:
            return None
        
        loopLen = self.isLoop(pHead)
        if not loopLen:
            return None
        else:
            p1 = pHead
            p2 = pHead
            for i in range(loopLen):
                p1= p1.next
            while p1 is not p2:
                p1 = p1.next
                p2 = p2.next
            return p1
        
    def isLoop(self,pHead):
        fast = pHead
        slow = pHead
        cfast = 0
        cslow = 0
        while fast.next is not None and fast.next.next is not None:
            fast = fast.next.next
            slow = slow.next
            cfast+=2
            cslow+=1
            if fast is slow:
                break
        if fast is slow:
            return cfast-cslow
        else:
            return 0

运行时间:24ms

占用内存:5708k

posted @ 2019-02-23 22:07  大胖子球花  阅读(91)  评论(0)    收藏  举报