該問題能夠差分爲三個子問題:java
1)最簡單的方法,使用HashSet,一邊遍歷將節點放到Set中,一邊檢查Set中節點是否重複,若是發現重複直接返回,該方法使用了額外的空間。node
import java.util.HashSet; import java.util.Set; public class NodeDemo { public static class Node{ public int value; public Node next; public Node(int data){ this.value = data; } } public static Node getLoopNode(Node node){ Set<Node> set = new HashSet<>(); //用來保存節點,檢查是否有重複出現的節點,若是有就是相交的節點,直接返回 Node cur = node; while(cur != null){ if (!set.contains(cur)) { set.add(cur); }else { return cur; } cur = cur.next; } return null; } public static void main(String[] args) { Node node = new Node(1); Node head = node; node.next = new Node(2); node.next.next = new Node(3); node.next.next.next = new Node(4); node.next.next.next.next = new Node(5); node.next.next.next.next.next = new Node(6); node.next.next.next.next.next.next = head.next.next; Node node1 = getLoopNode(node); System.out.println(node1.value); //輸出重複節點的值 } }
2)不使用額外空間的方法:oop
public static Node getLoopNode(Node head) { if (head == null || head.next == null || head.next.next == null) { return null; } Node n1 = head.next; //慢指針 Node n2 = head.next.next; //快指針 while (n1 != n2) { if (n2.next == null || n2.next.next == null) { return null; } n2 = n2.next.next; n1 = n1.next; } n2 = head; //快指針從新指向頭節點 while (n1 != n2) { n1 = n1.next; n2 = n2.next; } return n1; }
判斷條件:若是兩個無環鏈表有相同的尾節點,則相交,若是沒有則不相交。this
示意圖:spa
示意圖:指針
public static class Node{ public int value; public Node next; public Node(int data){ this.value = data; } } public Node noLoop(Node head1,Node head2){ if (head1 == null || head2 == null) return null; Node cur1 = head1; Node cur2 = head2; int n = 0; while (cur1.next != null) { n++; cur1 = cur1.next; } while (cur2.next != null) { n--; cur2 = cur2.next; } if (cur1 != cur2) //最後一個節點不相等,說明兩個鏈表不相交,直接返回null return null; cur1 = n > 0 ? head1 : head2; //cur1老是指向兩個鏈表中長的那一個 cur2 = cur1 == head1 ? head2: head1; n = Math.abs(n); while (n != 0) { n--; cur1 = cur1.next; } while (cur1 != cur2) { //當cur1和cur2相交的時候中止 cur1 = cur1.next; cur2 = cur2.next; } return cur1; }
兩個有環鏈表有三種狀況:code
第一種:blog
第二種:get
第三種:ast
public static Node bothLoop(Node head1, Node loop1, Node head2, Node loop2) { Node cur1 = null; Node cur2 = null; if (loop1 == loop2) { cur1 = head1; cur2 = head2; int n = 0; while (cur1 != loop1) { n++; cur1 = cur1.next; } while (cur2 != loop2) { n--; cur2 = cur2.next; } cur1 = n > 0 ? head1 : head2; cur2 = cur1 == head1 ? head2 : head1; n = Math.abs(n); while (n != 0) { n--; cur1 = cur1.next; } while (cur1 != cur2) { cur1 = cur1.next; cur2 = cur2.next; } return cur1; } else { cur1 = loop1.next; while (cur1 != loop1) { if (cur1 == loop2) { return loop1; } cur1 = cur1.next; } return null; } }
注:一個鏈表有環,一個鏈表無環不可能存在相交問題。