剑指 Offer 23. 链表中环的入口结点

题目描述:

      给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。

解题思路:

1、双指针:
     可以使用快慢双指针的做法,初始化precur指针都指向链表的首节点,然后pre指针每次沿着链表移动两步,cur指针每次沿着链表移动一步,如果链表中存在环,则precur指针一定会相遇,且一定会在环中的某个节点相遇。
     设链表的头结点为head,环的开始节点为p1precur指针相遇的节点为p2headp1的距离设为xp1p2的距离设为yp2p1的距离设为z,那么precur相遇时pre和cur走的距离分为x+yx+2y+z。因此2(x+y) = x+2y+z,即x = z,也就是precur相遇时headp1的距离x等于p2p1的距离z,因此这个时候将cur置为head,然后precur每次沿着链表移动一步,当precur指针再次相遇的节点即该链表的环的入口节点。

2、利用hashset:
     可以利用hashSet的特点,每次遍历链表的一个节点,如果该节点不在hastSet中则将该节点存在hastSet中,否则该节点即该链表的环的入口节点。

实现代码:

	//解法1:利用hashset(牛客网上编译不了)
    public ListNode EntryNodeOfLoop(ListNode pHead) {
        if(pHead == null)
            return null;
        HashSet<ListNode> set = new HashSet<ListNode>();
        ListNode cur = pHead;
        while(cur != null){
            if(!set.contains(cur))
                set.add(cur);
            else
                return cur;
            cur = cur.next;
        }
        return null;
    }

    //解法2:快慢双指针
    public ListNode EntryNodeOfLoop1(ListNode pHead) {
        if(pHead == null || pHead.next == null || pHead.next.next == null)
            return null;
        ListNode cur = pHead.next;
        ListNode pre = pHead.next.next;
        while(cur != pre){
            if (cur.next != null && pre.next != null && pre.next.next != null){
                cur = cur.next;
                pre = pre.next.next;
            }else
                return null;
        }
        cur = pHead;
        while(cur != pre){
            cur = cur.next;
            pre = pre.next;
        }
        return cur;
    }
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页