文章目录
142.环形链表II (20201010)
1.题目描述
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是-1,则在该链表中没有环。注意,pos 仅仅是用于标识环的情况,并不会作为参数传递到函数中。
说明:不允许修改给定的链表。
进阶:
你是否可以不用额外空间解决此题?
2.题目示例
- 提示
- 链表中节点的数目范围在范围 [0, 104] 内
- 105 <= Node.val <= 105
- pos 的值为 -1 或者链表中的一个有效索引
3.思路及代码
1.思路一:利用set,遍历,如果遇到有重复的,直接返回这个节点就可以了。
- 代码:
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode detectCycle(ListNode head) {
//遍历指针
ListNode cur = head;
//定义set集合
Set<ListNode> set = new HashSet<>();
//只要不为空就继续
while(cur != null){
//如果set中含有了,说明之前加过了,直接返回这个节点即可
if(set.contains(cur)){
return cur;
}else{
//加入
set.add(cur);
}
//继续走
cur = cur.next;
}
//未找到
return null;
}
}
- 运行结果:
思路二:这题乍一看和环形链表非常的像,只是有一点不太一样,要求输出的不一样,但是依然可以利用双指针来解决,具体原理,可以上力扣官网看大佬用数学证明。
- 代码:
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode detectCycle(ListNode head) {
//定义快慢指针
ListNode slow = head;
ListNode fast = head;
//边界条件
while(fast != null && fast.next != null){
//快== 2 * 慢
slow = slow.next;
fast = fast.next.next;
//相遇,说明有环,这时,定义res指针从head出发,与low相遇那么就返回该节点
if(slow == fast){
ListNode res = head;
while(res != slow){
slow = slow.next;
res = res.next;
}
//相遇
return res;
}
}
return null;
}
}
- 运行结果: