该问题能够差分为三个子问题: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; } }
注:一个链表有环,一个链表无环不可能存在相交问题。