总体思路
- 1.首先是判断两个链表是否有环,有的话返回其环的入口 没有返回null
- 2.一共两种情况 (1)两个无环链表相交(2)两个有环链表相交 (至于为啥没有一个有环一个没环的相交 因为我们的是单链表)
- 其中两个有环链表相交又分为三种情况:
- 其中两个有环链表相交又分为三种情况:
先总结下涉及到的小知识点:
(1)求单链表是否有环 如果有环,返回环入口的第一个节点否则返回null
- 细节思路:利用快慢指针做,快的一次两步慢的一次一步,快慢相交后,快从头指针开始走,一次改为一步,快慢同时开始走,相遇的就是环的第一个节点(你也可以用哈希表,就是费空间)
(2)求两个无环单链表是否相交,相交返回第一个相交的节点否则返回null
- 细节思路:先求两个链表大小的差值,长的那个先走到跟短的一样长后,开始一起走,相遇到就是返回,到头了返回null
(3)两个有环单链表是否相交,相交返回第一个相交的几节点,否则返回null
细节思路:见图 对于两个链表的第一个入环节点相同的情况(其实比较的是第一个入环节点的内存地址是否相同)直接转化为求两个无环链表第一个相交的节点的情况
细节思路:对于两个链表的第一个入环节点不相同的情况,则从第一个链表的入环节点的下一个节点开始走,如果碰到了第二个链表的入环节点,那么,返回第一个链表或者第二个链表的入环节点均可,因为都是第一个,只是跟原先的链表的距离不同而已。如果走完没找到 那么就是图中的第一种情况了,直接返回null。
首先 让我们看一下实现总体功能的函数(就是我们直接调用的函数):
public static Node getIntersectNode(Node head1, Node head2){ // 1.首先是判断两个链表是否有环,有的话返回其环的入口 没有返回null // 2.一共两种情况 (1)两个无环链表相交(2)两个有环链表相交 // 至于为啥没有一个有环一个没环的 相交 因为我们的是单链表 if(head1 == null || head2 == null){ return null; } //1.先求两个节点的入环节点 Node loop1 = getLoopNode(head1); Node loop2 = getLoopNode(head2); if(loop1 == null && loop2 == null){ return noLoop(head1, head2); } if (loop1 != null && loop2 != null){ return bothLoop(head1, loop1, head2, loop2); } return null; }
- 下面是求单链表是否有环的代码:
//给一个链表 返回其入环第一个节点 public static Node getLoopNode(Node head){ //首先是最少三个节点才能成环 if(head == null || head.next == null || head.next.next == null){ return null; } Node slow = head.next; Node first = head.next.next; while (first != slow){ if(first.next == null || first.next.next == null){ return null; } first = first.next.next; slow = slow.next; } first = head; while (first != slow){ first = first.next; slow = slow.next; } return first; }
- 下面是求两个无环单链表是否相交的代码:
//这是求 两个无环链表相交的第一个节点 public static Node noLoop(Node head1, Node head2){ int len1 = 0; int len2 = 0; Node cur1 = head1; Node cur2 = head2; while (head1 != null){ len1++; head1 = head1.next; } while (head2 != null){ len2++; head2 = head2.next; } int n = len1 - len2; if(n > 0){ while (n > 0){ n--; cur1 = cur1.next; } while (cur1 != null){ if(cur1 == cur2){ return cur1; } cur1 = cur1.next; cur2 = cur2.next; } return null; }else if(n < 0){ n = Math.abs(n); while (n > 0){ n--; cur2 = cur2.next; } while (cur1 != null){ if(cur1 == cur2){ return cur1; } cur1 = cur1.next; cur2 = cur2.next; } return null; }else{ while (cur1 != null){ if(cur1 == cur2){ return cur1; } cur1 = cur1.next; cur2 = cur2.next; } return null; } }
- 下面是求有环单链表是否相交的代码:
//(2)两个有环链表相交 一共三种情况: // 1.无交点 // 2.两个环的交点是一个 // 3.两个环的交点不是一个 public static Node bothLoop(Node head1, Node loop1, Node head2, Node loop2){ Node cur1 = null; Node cur2 = null; int n1 = 0; int n2 = 0; //第2种情况 if(loop1 == loop2){ cur1 = head1; cur2 = head2; while (cur1 != loop1){ n1++; cur1 = cur1.next; } while (cur2 != loop2){ n2++; cur2 = cur2.next; } int n3 = n1 - n2; cur1 = head1; cur2 = head2; if(n3 > 0){ while (n3 > 0){ n3--; cur1 = cur1.next; } while (cur1 != loop1){ if(cur1 == cur2){ return cur1; } cur1 = cur1.next; cur2 = cur2.next; } return cur1; }else if(n3 < 0){ n3 = Math.abs(n3); while (n3 > 0){ n3--; cur2 = cur2.next; } while (cur1 != loop2){ if(cur1 == cur2){ return cur1; } cur1 = cur1.next; cur2 = cur2.next; } return cur1; }else { while (cur1 != loop1){ if(cur1 == cur2){ return cur1; } cur1 = cur1.next; cur2 = cur2.next; } return cur1; } } else{ Node p = loop1.next; while (p != loop1){ if(p == loop2){ return loop1; } p = p.next; } return null; } }
- 最后是我们的主函数,就是测试函数:
public static void main(String[] args) { // 1->2->3->4->5->6->7->null Node head1 = new Node(1); head1.next = new Node(2); head1.next.next = new Node(3); head1.next.next.next = new Node(4); head1.next.next.next.next = new Node(5); head1.next.next.next.next.next = new Node(6); head1.next.next.next.next.next.next = new Node(7); // 0->9->8->6->7->null Node head2 = new Node(0); head2.next = new Node(9); head2.next.next = new Node(8); head2.next.next.next = head1.next.next.next.next.next; // 8->6 System.out.println(getIntersectNode(head1, head2).value); System.out.println(noLoop(head1, head2).value); // 1->2->3->4->5->6->7->4... head1 = new Node(1); head1.next = new Node(2); head1.next.next = new Node(3); head1.next.next.next = new Node(4); head1.next.next.next.next = new Node(5); head1.next.next.next.next.next = new Node(6); head1.next.next.next.next.next.next = new Node(7); head1.next.next.next.next.next.next = head1.next.next.next; // 7->4 // 0->9->8->2... head2 = new Node(0); head2.next = new Node(9); head2.next.next = new Node(8); head2.next.next.next = head1.next; // 8->2 System.out.println(getIntersectNode(head1, head2).value); // 0->9->8->6->4->5->6.. head2 = new Node(0); head2.next = new Node(9); head2.next.next = new Node(8); head2.next.next.next = head1.next.next.next.next.next; // 8->6 System.out.println(getIntersectNode(head1, head2).value); }