前言
环形链表相关的问题,在链表中出现的也很多, 因此总结下环形链表相关的问题
- NC4 判断链表中是否有环(简单)
- NC3 链表中环的入口结点(中等)
1. 判断链表中是否有环
描述 : 判断给定的链表中是否有环。如果有环则返回true,否则返回false。
思路分析: 快慢指针, 慢指针针每次走一步,快指针每次走两步,如果相遇就说明有环,否则就说明无环
AC 代码:
public boolean hasCycle(ListNode head) {
ListNode slow = head;
ListNode fast = head;
while(fast != null && fast.next != null){
fast = fast.next.next;
slow = slow.next;
if(fast == slow){
return true;
}
}
return false;
}
2. 链表中环的入口结点
描述:给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,返回null。
思路分析:
- 遍历链表 使用 Set 记录出现的节点, 当第一个重复节点出现时, 这个节点即为入环节点, 如果遍历完之后,都没有重复节点, 说明节点无环
- 快慢指针, 当快慢指针相遇时, 让快指针移动到 head , 然后快慢指针 一起走, 再次相遇后,即为入环节点
A 为起始节点, B 是 入环节点, C 是第一次相遇的节点, D 是当慢指针到B 时 快指针的位置
第一次相遇的 慢指针走过 x + y
快指针 走过 2*(x + y) AB + BC + CD + DB + BC
x + y + CD +y + y = 2x + 2y
CD的长度 x - y 那么 BC 为x
所以当快慢指针相遇时, 让快指针移动到 head , 然后快慢指针 一起走, 再次相遇后,即为入环节点
AC 代码:
使用 Set 实现的版本, 时间复杂度 O(n) 空间复杂度 O(n)
public ListNode EntryNodeOfLoop(ListNode pHead) {
Set<ListNode> set = new HashSet<>();
while(pHead != null){
if(set.contains(pHead)){
return pHead;
}
set.add(pHead);
pHead = pHead.next;
}
return null;
}
快慢指针版本 时间复杂度 O(n) 空间复杂度 O(1)
public ListNode EntryNodeOfLoop(ListNode pHead) {
ListNode slow = pHead;
ListNode fast = pHead;
while(fast != null && fast.next != null){
fast = fast.next.next;
slow = slow.next;
if(slow == fast){
break;
}
}
if(fast == null || fast.next == null){
return null;
}
fast = pHead;
while(fast != slow){
slow = slow.next;
fast = fast.next;
}
return fast;