给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
说明:不允许修改给定的链表。
链接:https://leetcode-cn.com/problems/linked-list-cycle-ii
自己的代码以及思路:
1.先通过快慢指针找到相交的点。(这边快慢指针好像都是从头开始的,然后我的快指针是从head.next开始的,会差一位)
2.然后其中一个指针从相交的点出发,头结点从头出发,两个点相交的点就是环中第一个相交的点。
/** * 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) { if (head == null || head.next == null) { return null; } //step1 find meet ListNode slow = head; ListNode fast = head.next; ListNode meet= new ListNode(-999); ListNode head_copy= new ListNode(-999); head_copy=head; while (slow != fast) { if (fast == null || fast.next == null) { return null; } slow = slow.next; fast = fast.next.next; } System.out.println(slow.val); System.out.println(fast.val); meet=fast.next; // head_copy=head; while(meet!=head_copy) { // System.out.println("meet"+meet.val); // System.out.println("head_copy"+head_copy.val); meet=meet.next; head_copy=head_copy.next; } return head_copy; } }
Leetcode题解的方法:
方法 1:哈希表
想法
如果我们用一个 Set 保存已经访问过的节点,我们可以遍历整个列表并返回第一个出现重复的节点。
算法
首先,我们分配一个 Set 去保存所有的列表节点。我们逐一遍历列表,检查当前节点是否出现过,如果节点已经出现过,那么一定形成了环且它是环的入口。否则如果有其他点是环的入口,我们应该先访问到其他节点而不是这个节点。其他情况,没有成环则直接返回 null 。
算法会在遍历有限个节点后终止,这是因为输入列表会被分成两类:成环的和不成环的。一个不成环的列表在遍历完所有节点后会到达 null - 即链表的最后一个元素后停止。一个成环列表可以想象成是一个不成环列表将最后一个 null 元素换成环的入口。
如果 while 循环终止,我们返回 null 因为我们已经将所有的节点遍历了一遍且没有遇到重复的节点,这种情况下,列表是不成环的。对于循环列表, while 循环永远不会停止,但在某个节点上, if 条件会被满足并导致函数的退出。
public class Solution { public ListNode detectCycle(ListNode head) { Set<ListNode> visited = new HashSet<ListNode>(); ListNode node = head; while (node != null) { if (visited.contains(node)) { return node; } visited.add(node); node = node.next; } return null; } }
方法2:和那个视频里讲的是一样的。
public class Solution { private ListNode getIntersect(ListNode head) { ListNode tortoise = head; ListNode hare = head; // A fast pointer will either loop around a cycle and meet the slow // pointer or reach the `null` at the end of a non-cyclic list. while (hare != null && hare.next != null) { tortoise = tortoise.next; hare = hare.next.next; if (tortoise == hare) { return tortoise; } } return null; } public ListNode detectCycle(ListNode head) { if (head == null) { return null; } // If there is a cycle, the fast/slow pointers will intersect at some // node. Otherwise, there is no cycle, so we cannot find an e***ance to // a cycle. ListNode intersect = getIntersect(head); if (intersect == null) { return null; } // To find the e***ance to the cycle, we have two pointers traverse at // the same speed -- one from the front of the list, and the other from // the point of intersection. ListNode ptr1 = head; ListNode ptr2 = intersect; while (ptr1 != ptr2) { ptr1 = ptr1.next; ptr2 = ptr2.next; } return ptr1; } }