题目描述:给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
刚看到这道题,想着用HashSet,但这毕竟是算法题,应尽量避免使用工具类;HashSet解法:
public ListNode EntryNodeOfLoop(ListNode pHead) { HashSet<ListNode> hashSet = new HashSet<>(); while (pHead != null){ if (hashSet.contains(pHead)) { return pHead; }else { hashSet.add(pHead); pHead = pHead.next; } } return null; }
然后看题解,看到了这个链接
思路:
创建快慢指针,slow、fast,如果有环,快慢指针总有指向同一个节点的时候,设置标记;否则当快指针等于null的时候,也就停止了;
判断标记,如果为false,返回null;否则,进行下一步;
计算环的长度;
使快指针先移动一个环的长度,然后快慢指针同时移动,直到快慢指针相等,该节点即环的入口节点;
public ListNode EntryNodeOfLoop(ListNode pHead) { ListNode slow = pHead; ListNode fast = pHead; boolean flag = false; // 判断是否有环 while (fast != null && fast.next != null){ slow = slow.next; fast = fast.next.next; if (slow == fast){ flag = true; break; } } // 没有环直接返回null if (!flag) return null; // 有环, 计算出环的长度 ListNode workNode = slow; int count = 1; workNode = workNode.next; // slow对应节点开始计数1,直到workNode==slow,计数完成 while (workNode != slow){ count++; workNode = workNode.next; } slow = pHead; fast = pHead; //移动一个环的长度 for (int i = 0; i < count; i++) { fast = fast.next; } // 快慢指针同时移动,直到相等 while (slow != fast){ slow = slow.next; fast = fast.next; } return slow; }