// 获取相交节点
public static Node getNode(Node head1, Node head2) {
if (head1 == null || head2 == null) {
return null;
}
// 获取第一个链表的入环节点
Node loop1 = getLoopNode(head1);
// 获取第二个链表的入环节点
Node loop2 = getLoopNode(head2);
// 如果2个为空,则代表2个链表均无环
if (loop1 == null && loop2 == null) {
return noLoop(head1, head2);
}
// 如果均有环
if (loop1 != null && loop2 != null) {
return bothLoop(head1, loop1, head2, loop2);
}
return null;
}
// 获取无环的2个链表的相交节点
public static Node noLoop(Node head1, Node head2) {
int len1 = 0;
int len2 = 0;
Node n1 = head1;
Node n2 = head2;
// 获取第一个链表的长度
while (n1.next != null) {
len1++;
n1 = n1.next;
}
// 获取第二个链表的长度
while (n2.next != null) {
len2++;
n2 = n2.next;
}
// 如果尾部节点不一致,则2个链表无公共部分
if (n1 != n2) {
return null;
}
// 求2个长度的差值
int c = Math.abs(len1 - len2);
// 找到最长的链表
Node h = len1 > len2 ? head1 : head2;
// 最短的链表
Node h2 = len1 > len2 ? head2 : head1;
// 让最长的链表多走c步,使2个链表的长度一致
while (c > 0) {
h = h.next;
c--;
}
// 2个链表同时遍历,直到相等节点,则为相交节点
while (h != h2) {
h = h.next;
h2 = h2.next;
}
return h;
}
public static Node bothLoop(Node head1, Node loop1, Node head2, Node loop2) {
if (loop1 == loop2) {
int len1 = 0;
int len2 = 0;
Node n1 = head1;
Node n2 = head2;
while (n1 != loop1) {
len1++;
n1 = n1.next;
}
while (n2 != loop1) {
len2++;
n2 = n2.next;
}
// 如果尾部节点不一致,则2个链表无公共部分
if (n1 != n2) {
return null;
}
int c = Math.abs(len1 - len2);
Node h = len1 > len2 ? head1 : head2;
Node h2 = len1 > len2 ? head2 : head1;
while (c > 0) {
h = h.next;
c--;
}
while (h != h2) {
h = h.next;
h2 = h2.next;
}
return h;
} else {
Node cur = loop1.next;
while (cur != loop1) {
if (cur == loop2) {
return loop1;
}
cur = cur.next;
}
return null;
}
}
public static Node getLoopNode(Node head) {
if (head == null || head.next == null) {
return null;
}
// 快慢指针,快指针一定会遇到慢指针
Node n1 = head.next;
Node n2 = head.next.next;
while (n2 != null && n2.next != null) {
if (n1 == n2) {
break;
}
n1 = n1.next;
n2 = n2.next.next;
}
// 将快指针重置到头节点,慢指针保留原地,2个指针同时走,一定会在入环节点相遇
n2 = head;
while (n1 != null && n2 != null) {
if (n1 == n2) {
break;
}
n1 = n1.next;
n2 = n2.next;
}
return n1;
}
算法:寻找无环或者有环的2个单向链表的相交节点
最新推荐文章于 2024-05-03 10:14:52 发布