【劍指Offer學習】【面試題56:連結串列中環的入口結點】
阿新 • • 發佈:2018-12-31
題目:一個連結串列中包含環,如何找出環的入口結點?
解題思路
可以用兩個指標來解決這個問題。先定義兩個指標P1和P2指向連結串列的頭結點。如果連結串列中環有n個結點,指標P1在連結串列上向前移動n步,然後兩個指標以相同的速度向前移動。當第二個指標指向環的入口結點時,第一個指標已經圍繞著環走了一圈又回到了入口結點。
剩下的問題就是如何得到環中結點的數目。我們在面試題15的第二個相關題目時用到了一快一慢的兩個指標。如果兩個指標相遇,表明連結串列中存在環。兩個指標相遇的結點一定是在環中。可以從這個結點出發,一邊繼續向前移動一邊計數,當再次回到這個結點時就可以得到環中結點數了。
結點定義
private static class ListNode {
private int val;
private ListNode next;
public ListNode() {
}
public ListNode(int val) {
this.val = val;
}
@Override
public String toString() {
return val +"";
}
}
程式碼實現
public class Test56 {
private static class ListNode {
private int val;
private ListNode next;
public ListNode() {
}
public ListNode(int val) {
this.val = val;
}
@Override
public String toString() {
return val +"";
}
}
public static ListNode meetingNode(ListNode head) {
ListNode fast = head;
ListNode slow = head;
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;
}
// fast重新指向第一個結點
fast = head;
while (fast != slow) {
fast = fast.next;
slow = slow.next;
}
return fast;
}
public static void main(String[] args) {
test01();
test02();
test03();
}
// 1->2->3->4->5->6
private static void test01() {
ListNode n1 = new ListNode(1);
ListNode n2 = new ListNode(2);
ListNode n3 = new ListNode(3);
ListNode n4 = new ListNode(4);
ListNode n5 = new ListNode(5);
ListNode n6 = new ListNode(6);
n1.next = n2;
n2.next = n3;
n3.next = n4;
n4.next = n5;
n5.next = n6;
System.out.println(meetingNode(n1));
}
// 1->2->3->4->5->6
// ^ |
// | |
// +--------+
private static void test02() {
ListNode n1 = new ListNode(1);
ListNode n2 = new ListNode(2);
ListNode n3 = new ListNode(3);
ListNode n4 = new ListNode(4);
ListNode n5 = new ListNode(5);
ListNode n6 = new ListNode(6);
n1.next = n2;
n2.next = n3;
n3.next = n4;
n4.next = n5;
n5.next = n6;
n6.next = n3;
System.out.println(meetingNode(n1));
}
// 1->2->3->4->5->6 <-+
// | |
// +---+
private static void test03() {
ListNode n1 = new ListNode(1);
ListNode n2 = new ListNode(2);
ListNode n3 = new ListNode(3);
ListNode n4 = new ListNode(4);
ListNode n5 = new ListNode(5);
ListNode n6 = new ListNode(6);
n1.next = n2;
n2.next = n3;
n3.next = n4;
n4.next = n5;
n5.next = n6;
n6.next = n6;
System.out.println(meetingNode(n1));
}
}