我的LeetCode代码仓:https://github.com/617076674/LeetCode
原题链接:https://leetcode-cn.com/problems/linked-list-cycle-ii/description/
题目描述:
知识点:哈希表、双指针、链表
思路一:用一个hashSet来存储已经遍历过的节点
本题是LeetCode141——环形链表的加强版。
一旦发现某个节点的next节点已经被遍历过,则说明存在环,直接返回该next节点即可。否则,返回null。
时间复杂度和空间复杂度均是O(n),其中n为链表中的节点个数。
JAVA代码:
public class Solution {
public ListNode detectCycle(ListNode head) {
HashSet<ListNode> hashSet = new HashSet<>();
ListNode dummyHead = new ListNode(-1);
dummyHead.next = head;
ListNode cur = dummyHead;
while(null != cur.next){
if(hashSet.contains(cur.next)){
return cur.next;
}
cur = cur.next;
hashSet.add(cur);
}
return null;
}
}
LeetCode解题报告:
思路二:用快慢双指针遍历链表
快指针一次移动两步,慢指针依次移动一步。将快慢双指针想象成两个运动员在赛跑,如果链表有环,那么终有一个时刻快慢双指针会重合。一旦某个节点的next节点出现null,说明不是环形链表,直接返回null即可。
如果是环形链表,我们令其中一个指针指向虚拟头节点,而另一个指针则仍然在相遇的那个节点,一起移动这两个指针,直到这两个指针相遇,这个新的相遇点就是链表开始入环的第一个节点。
为什么上述算法得到的点就是链表开始入环的第一个节点呢?
如上图所示,虚拟头节点到第一个入环的节点的距离是x1,第一个入环的节点顺时针出发到相遇点的距离是x2,相遇点顺时针出发到第一个入环的节点的距离是x3。
从dummyHead节点出发到快慢指针相遇的过程中:
第一个慢指针走过的路程长度是x1 + x2。
第二个快指针走过的路程长度是x1 + x2 + x3 + x2。
由快慢指针的速度关系得:(x1 + x2) * 2 = x1 + x2 + x3 + x2,因此x1 = x3。因此,我们只需令其中一个指针指向虚拟头节点,而另一个指针则仍然在相遇的那个节点,一起移动这两个指针,直到这两个指针相遇,这个新的相遇点就是链表开始入环的第一个节点。
时间复杂度是O(n),其中n为链表中的节点个数。空间复杂度是O(1)。
JAVA代码:
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode dummyHead = new ListNode(-1);
dummyHead.next = head;
ListNode cur1 = dummyHead;
ListNode cur2 = dummyHead;
while(true){
if(null == cur2.next || null == cur2.next.next){
return null;
}
cur1 = cur1.next;
cur2 = cur2.next.next;
if(cur1 == cur2){
break;
}
}
cur1 = dummyHead;
while(cur1 != cur2){
cur1 = cur1.next;
cur2 = cur2.next;
}
return cur1;
}
}
LeetCode解题报告: