一. 问题描述
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
说明:不允许修改给定的链表。
示例 1:
输入:head = [3,2,0,-4], pos = 1
输出:tail connects to node index 1
解释:链表中有一个环,其尾部连接到第二个节点。
示例 2:
输入:head = [1,2], pos = 0
输出:tail connects to node index 0
解释:链表中有一个环,其尾部连接到第一个节点。
示例 3:
输入:head = [1], pos = -1
输出:no cycle
解释:链表中没有环。
进阶:
你是否可以不用额外空间解决此题?
二. 解题思路
解题思路:本题有两种解题思路分别是set表进行查询和双指针进行解题。
解题思路1:采用set表进行解题。
步骤一:依次访问链表,并将其存储在set表中,如果发现set表中包含所访问的链表说明该节点就是循环节点的头节点,如果访问到null都没有包含则返回null。
解题思路2:采用双指针进行求解。
步骤一:通过快慢指针,fast走两步,low走一步,如果存在循环链表的话,必定快指针在循环内与慢指针相遇。则通过数学公式我们可推到当相遇后从头节点tempfirst开始走和慢指针必定在环的第一个节点相遇(推导过程Leetcode上有)
步骤二:当tempfirst==first的时候输出first就是所需要的节点,当访问到null都没有时说明没有环,输出null
三. 执行结果
执行用时 :0 ms, 在所有 java 提交中击败了100.00%的用户
内存消耗 :37.6 MB, 在所有 java 提交中击败了56.49%的用户
四. Java代码
public ListNode detectCycle(ListNode head) { if(head==null||head.next==null) { return null; } ListNode first=head; ListNode second=head; do{ first=first.next; if(second.next!=null) { second=second.next.next; }else { return null; } }while(!(first==second)&&!(second==null)) ; if(first==second) { ListNode tempFirst=head; while(!(first==tempFirst)) { first=first.next; tempFirst=tempFirst.next; } return tempFirst; }else { return null; } }
第二种思路代码:
public class Solution { public ListNode detectCycle(ListNode head) { HashSet<ListNode> set=new HashSet<ListNode>(); if(head==null||head.next==null) { return null; } while(!(head==null)&&!set.contains(head)) { if(!set.contains(head)) { set.add(head); head=head.next; } } if(set.contains(head)) { return head; }else { return null; } } }