面试题23:链表中环的入口节点

一个链表中包含环,请找出该链表的环的入口结点。

思路一:利用set和map判重

/**
     * 利用set
     * @param pHead
     * @return
     */
    public ListNode EntryNodeOfLoop3(ListNode pHead) {
        if (pHead == null){
            return null;
        }
        Set set = new HashSet<>();
        ListNode cur = pHead;
        //最后一个也要遍历到
        while (cur != null){
            //如果重复值没有添加成功,则返回false,找到第一个重复值
            if (!set.add(cur)){
                return cur;
            }
            cur = cur.next;
        }
        return null;
    }

    /**
     * 利用map
     * @param pHead
     * @return
     */
    public ListNode EntryNodeOfLoop4(ListNode pHead) {
        if (pHead == null){
            return null;
        }
        Map map = new HashMap();
        ListNode cur = pHead;
        while (cur != null){
            //map中是否有重复主键,如果重复出现第一个,则是入口
            if (map.containsKey(cur)){
                return cur;
            }
            map.put(cur,true);
            cur=cur.next;
        }
        return null;
    }

基本思路:
先快慢节点判断链表是否有环,如果有环的话,从相遇位置开始,统计环中节点的个数,得到个数以后,使用两个节点,其中一个节点先走环的个数,此时和另一个节点重新开始,当他们再次相遇时,便是环的入口。
代码如下:

public class EntryNodeOfLoop {
    public class ListNode {
        int val;
        ListNode next = null;

        ListNode(int val) {
            this.val = val;
        }
    }
    public ListNode EntryNodeOfLoop(ListNode pHead)
    {
        if (pHead == null){
            return null;
        }
        ListNode node1 = null;
        if (isLoop(pHead) != null){
            node1 = isLoop(pHead);
        }else {
            return null;
        }
        ListNode node2 = node1;
        int len = 1;
        while (node2.next != node1){
            len++;
            node2 = node2.next;
        }
        ListNode p1 = pHead;
        ListNode p2 = pHead;
        for (int i=0;i

优化思路:
我们设链表的环的长度为n,一快一慢检验是否有环后,当再次相遇时,快指针正好别慢指针多走一个环的个数,设慢指针走过的节点数为x,快指针走过的节点数为2x,即2x = n + x,n = x,即慢指针正好走了一个环的个数,这时候我们把快指针重新指向链表的头结点,同时出发,当再次相遇时即为环的入口。
简单的来说就是当快慢指针相遇时,慢指针走的就是环的节点的个数,省去了根据环中节点重复找环的长度的过程。只要重置快指针即可完成不同初始位置同时出发直到相遇的条件。
代码如下:

* @param pHead
     * @return
     */
    public ListNode EntryNodeOfLoop2(ListNode pHead) {
        if (pHead == null){
            return null;
        }
        ListNode pfast = pHead;
        ListNode pslow = pHead;
        while (pfast.next != null && pslow.next != null){
             pfast = pfast.next.next;
             pslow = pslow.next;

             if (pfast == pslow){
                 pfast=pHead;
                 while (pslow != pfast){
                     pfast = pfast.next;
                     pslow = pslow.next;
                 }
                 return pslow;
             }
        }
        return null;
    }

你可能感兴趣的:(面试题23:链表中环的入口节点)