给一个长度为n链表,若其中包含环,请找出该链表的环的入口结点,否则,返回null。
数据范围: ,
要求:空间复杂度 ,时间复杂度
例如,输入{1,2},{3,4,5}时,对应的环形链表如下图所示:
可以看到环的入口结点的结点值为3,所以返回结点值为3的结点。
输入分为2段,第一段是入环前的链表部分,第二段是链表环的部分,后台会根据第二段是否为空将这两段组装成一个无环或者有环单链表
返回链表的环的入口结点即可,我们后台程序会打印这个结点对应的结点值;若没有,则返回对应编程语言的空结点即可。
{1,2},{3,4,5}
3
返回环形链表入口结点,我们后台程序会打印该环形链表入口结点对应的结点值,即3
{1},{}
"null"
没有环,返回对应编程语言的空结点,后台程序会打印"null"
{},{2}
2
环的部分只有一个结点,所以返回该环形链表入口结点,后台程序打印该结点对应的结点值,即2
public class Solution { //链表头到环入口的距离=相遇点到环入口的距离+(k-1)圈环长度 //判断有没有环,返回相遇的地方 public ListNode hasCycle(ListNode head) { //先判断链表为空的情况 if (head == null) return null; //快慢双指针 ListNode fast = head; ListNode slow = head; //如果没环快指针会先到链表尾 while (fast != null && fast.next != null) { //快指针移动两步 fast = fast.next.next; //慢指针移动一步 slow = slow.next; //相遇则有环,返回相遇的位置 if (fast == slow) return slow; } //到末尾说明没有环,返回null return null; } public ListNode EntryNodeOfLoop(ListNode pHead) { ListNode slow = hasCycle(pHead); //没有环 if (slow == null) return null; //快指针回到表头 ListNode fast = pHead; //再次相遇即是环入口 while (fast != slow) { fast = fast.next; slow = slow.next; } return slow; } }
import java.util.*; /* public class ListNode { int val; ListNode next = null; ListNode(int val) { this.val = val; } } */ public class Solution { public ListNode EntryNodeOfLoop(ListNode pHead) { //如果没有节点或者只有一个节点,就不可能有环入口,直接返回null if (pHead == null || pHead.next == null){ return null; } //我定义了一个快指针,一个慢指针,快指针每次跑两个节点,慢指针每次跑一个节点 ListNode fast = pHead; ListNode low = pHead; while (fast.next != null && fast.next.next != null){ low = low.next; fast = fast.next.next; if (low == fast){ //说明有环路 low = pHead; //让慢指针重新指向头节点,这次快慢指针每次都跑一个节点 while(low != fast){ low = low.next; fast = fast.next; } return low; } } //如果能走到这里,就说明没有环路,也返回null return null; } }
import java.util.*; /* public class ListNode { int val; ListNode next = null; ListNode(int val) { this.val = val; } } */ public class Solution { public ListNode EntryNodeOfLoop(ListNode pHead) { while(pHead != null && pHead.val > 0){ pHead.val = -pHead.val; pHead = pHead.next; } if(pHead == null){ return null; }else{ pHead.val = -pHead.val; return pHead; } } }
import java.util.*; /* public class ListNode { int val; ListNode next = null; ListNode(int val) { this.val = val; } } */ public class Solution { public ListNode EntryNodeOfLoop(ListNode pHead) { while(pHead != null){ if(pHead.val < 0){ pHead.val = pHead.val + Integer.MAX_VALUE; return pHead; }else{ pHead.val = pHead.val - Integer.MAX_VALUE; pHead = pHead.next; } } return null; } } 思路:走过更新数据为负数,当值为负数表示有环,把数还原回来,在这里使用了int最大值
public class Solution { public ListNode EntryNodeOfLoop(ListNode pHead) { HashSet<ListNode> hasCycleSet = new HashSet<>(); while(pHead != null){ if(hasCycleSet.contains(pHead)){ // 下一个节点已记录 return pHead; }else{ // 下一个节点未记录 hasCycleSet.add(pHead); } pHead = pHead.next; } return null; } }
public class Solution { public ListNode EntryNodeOfLoop(ListNode pHead) { ListNode slow = pHead; ListNode fast = pHead; while (fast != null && fast.next != null) { slow = slow.next; fast = fast.next.next; if (slow == fast) { ListNode index1 = slow; ListNode index2 = pHead; while (index1 != index2) { index1 = index1.next; index2 = index2.next; } return index2; } } return null; } }
public ListNode EntryNodeOfLoop(ListNode pHead) { if (pHead == null || !isLoop2(pHead)) return null; if (pHead.next == pHead) return pHead; ListNode prior = pHead; ListNode cur = pHead.next; while (isLoop2(prior)) { prior.next = null; prior = cur; cur = cur.next; } while (cur.next != null) { cur = cur.next; } return cur; } public boolean isLoop1(ListNode head) { int count = 0; while (count < 10001 && head != null) { count++; head = head.next; } return count == 10001; } public boolean isLoop2(ListNode head) { ListNode slow = head; ListNode fast = head; while (fast != null && fast.next != null) { fast = fast.next.next; slow = slow.next; if (slow == fast) { return true; } } return false; }剩余链表成环的条件被破坏后,cur 或 prior 的最终next 一定是入口节点
public ListNode EntryNodeOfLoop(ListNode pHead) { if(pHead == null || pHead.next == null){ return null; } List<ListNode> list = new ArrayList<>(); while(pHead != null){ if(list.contains(pHead)){ //如果包含,说明已经出现环了,且入口就是它 return pHead; } list.add(pHead); pHead = pHead.next; } return null; }
public ListNode EntryNodeOfLoop(ListNode pHead) { //只有一个链 ListNode fast=pHead; ListNode slow=pHead; while(fast!=null&&fast.next!=null){ fast=fast.next.next; slow=slow.next; while(fast==slow){ ListNode index1=fast;//一个从fast走,一个从pHead走 ListNode index2=pHead; while(index1!=index2){ index1=index1.next; index2=index2.next; } return index1;//如果找到环的入口,就return index1 } } return null;//如果没有找到return null }
import java.util.*; /* public class ListNode { int val; ListNode next = null; ListNode(int val) { this.val = val; } } */ public class Solution { public ListNode EntryNodeOfLoop(ListNode pHead) { if (pHead == null || pHead.next == null) { return null; } ListNode fast = pHead; ListNode slow = pHead; while (fast != null && fast.next != null) { fast = fast.next.next; slow = slow.next; if (fast == slow) { break; } } if (fast == null || fast.next == null) { return null; } slow = pHead; while (fast != slow) { fast = fast.next; slow = slow.next; } return slow; } }
import java.util.*; /* public class ListNode { int val; ListNode next = null; ListNode(int val) { this.val = val; } } */ public class Solution { public ListNode EntryNodeOfLoop(ListNode pHead) { Set<ListNode> set =new HashSet<>(); ListNode cur = pHead; ListNode res = null; while(cur != null) { if(set.contains(cur)) { res = cur; break; } set.add(cur); cur = cur.next; } return res; } }
当第二个指针指向环的入口结点时,第一个指针已经围绕着环走了一圈又回到了入口结点。