问题一
给定一个链表,判断链表中是否有环。
解题思路:
可以设定两个指针p与q,初始都指向链表的起始点(head),p每次跳一步而q每次两步。
若链表中存在环,则p与q一定相遇。
代码如下:
public static boolean hasCycle(ListNode head) { if (head == null) return false; ListNode p = head; ListNode q = head; while (true) { if (q == null || q.next == null) return false; p = p.next; q = q.next.next; if (p == q) return true; } }
问题二
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null
。
解题思路:
设定两个指针p与q,初始都指向链表的起始点(head),p每次跳一步而q每次两步。
设链表中非环节点由m个,环节点有n个。
当p指针到达环的第一个节点时,p与q都位于环中,p跳了m步,q跳了2m步,p与q相距m步,q与p相距n-m步。
(如上图所示,m=3,n=7 。当p跳3步到达环的第一个节点时,p与q相距3步,q与p相距4步。)
由于q每次必p多走一步,故两个指针需要再跳n-m次才能相遇。此时相遇点与环的起始点相距m步,而head与环的起始点也相距m步。
故head每次跳一步,p每次跳一步,二者的相聚点即是环的第一个节点。
代码如下:
public static ListNode detectCycle(ListNode head) { if (head == null) return null; ListNode p = head; ListNode q = head; while (true) { if (q == null || q.next == null) return null; p = p.next; q = q.next.next; if (p == q) break; } while (head != q) { head = head.next; q = q.next; } return head; }