两链表相交及其第一个节点
判断有无环,如果有环返回第一个入环节点,如果无环返回null
沿着指针将a、b、c、d、e、c放入set结构中,每次放入前查看在set集合中是否存在;
若遍历到null都没有重复节点,那么链表为无环链表;
若有重复,链表有环,第一个重复的值即为第一个入环节点
如果一个链表无环,一定能够指向null
如果一个链表有环,最终它一定在一直循环
快慢指针:快指针一次走两步,慢指针一次走一步
如果一个链表无环,快指针先指向null
如果一个链表有环,快满指针一定会在某一时刻相遇
(不一定在入环节点相遇并且慢指针在环中转的圈数不超过两圈)
相遇之后,慢指针在原地,快指针回到起点,接下来快慢指针都走一步,两个指针一定会在入环节点相遇(数学证明)
- //判断有环无环,有环返回第一个入环节点,无环返回null
- public static Node getloopNode(Node head) {
-
- if (head == null || head.next == null || head.next.next == null) {
- return null;
- }
-
- //快慢指针相遇的时候停止,如果快慢指针都从head出发,开始时相遇,所以快指针先走两步,慢指针走一步
- Node slow = head.next;
- Node fast = head.next.next;
- while (slow != fast) {
- if (fast.next == null || fast.next.next == null) {//无环
- return null;
- }
-
- slow = slow.next;
- fast = fast.next.next;
- }
-
- fast = head;//回到开头
- while (slow != fast) {
- slow = slow.next;
- fast = fast.next;
- }
-
- return slow;
- }
两个链表分别调用getloopNode方法
loop1 == null loop2 == null
不可能如左图所示,单链表只能有一个next指针;如果两链表相交,一定是右图所示
先遍历两个链表,记录两链表的长度;
比较链表最后一个Node,如果相等,则两链表相交;若不相等,则两链表不相交
长链表先走两个链表之间的长度差,之后两链表再一起走,两链表在第一个相交节点处相遇
- //如果两个链表都无环,判断两链表是否相交,相交则返回第一个相交节点,不相交则返回null
- public static Node noLoop(Node head1, Node head2) {
- if (head1 == null || head2 == null) {
- return null;
- }
-
- int length1 = 0, length2 = 0;
- //遍历链表1
- while (head1.next != null) {//链表1在最后一个节点停
- length1++;
- head1 = head1.next;
- }
- //遍历链表2
- while (head2.next != null) {//链表2在最后一个节点停
- length2++;
- head2 = head2.next;
- }
-
- if (head1 == head2) {//不相交
- return null;
- } else {
- while(head1 != head2){//还没相遇
- if (length1 > length2) {//链表1较长
- length1--;
- head1 = head1.next;
-
- } else if (length1 < length2) {//链表2较长
- length2--;
- head2 = head2.next;
-
- } else {//长链表先走了差值长度之后,两链表一起走直到相遇
- head1 = head1.next;
- head2 = head2.next;
- }
- }
- }
-
- return head1;
- }
此种情况两链表不可能相交,一定会有某个节点有两个next指针
情况2:求相交节点 = 两无环单链表求相交节点
把入环节点看成结尾,终止节点为loop1==loop2
情况1和情况3:loop1继续向下走,如果在循环中没有遇到loop2,则两链表不相交;
如果在循环的过程中遇到了loop2,则两链表相交
返回的结果既可以是loop1,也可以是loop2,两个节点都是两链表的相交节点
- //如果两个链表都有环,判断两链表是否相交,相交则返回第一个相交节点,不相交则返回null
- //loop1 = getloopNode(head1); loop2 = getloopNode(head2);
- public static Node bothLoop(Node head1, Node head2, Node loop1, Node loop2) {
-
- if (loop1 == loop2) {//情况2
-
- int length1 = 0, length2 = 0;
- //遍历链表1
- while (head1.next != null) {//链表1在最后一个节点停
- length1++;
- head1 = head1.next;
- }
- //遍历链表2
- while (head2.next != null) {//链表2在最后一个节点停
- length2++;
- head2 = head2.next;
- }
-
- if (head1 == head2) {//不相交
- return null;
- } else {
- while (head1 != head2) {//还没相遇
- if (length1 > length2) {//链表1较长
- length1--;
- head1 = head1.next;
-
- } else if (length1 < length2) {//链表2较长
- length2--;
- head2 = head2.next;
-
- } else {//长链表先走了差值长度之后,两链表一起走直到相遇
- head1 = head1.next;
- head2 = head2.next;
- }
- }
- }
- return head1;
-
- } else {//情况1和情况3
-
- Node temp = loop1.next;
- while (temp != loop1) {//在圈里面遍历
-
- if (temp == loop2) {//遇到loop2,情况3
- return loop1;//return loop2;
- }
- temp = temp.next;
- }
-
- return null;//情况1
- }
- }
调用
- public static Node getIntersectNode(Node head1,Node head2){
- if(head1 == null || head2 == null){
- return null;
- }
-
- Node loop1 = getloopNode(head1);
- Node loop2 = getloopNode(head2);
- if(loop1 == null && loop2 == null){
- return noLoop(head1,head2);
- } else if (loop1 != null && loop2 != null) {
- return bothLoop(head1,head2,loop1,loop2);
- }else{
- return null;
- }
- }
全代码
- package linkedlist;
-
- public class IntersectLinkedList {
- class Node {
- public int value;
- public Node next;
-
- public Node(int data) {
- this.value = data;
- }
-
- }
-
- //判断有环无环,有环返回第一个入环节点,无环返回null
- public static Node getloopNode(Node head) {
-
- if (head == null || head.next == null || head.next.next == null) {
- return null;
- }
-
- //快慢指针相遇的时候停止,如果快慢指针都从head出发,开始时相遇,所以快指针先走两步,慢指针走一步
- Node slow = head.next;
- Node fast = head.next.next;
- while (slow != fast) {
- if (fast.next == null || fast.next.next == null) {//无环
- return null;
- }
-
- slow = slow.next;
- fast = fast.next.next;
- }
-
- fast = head;//回到开头
- while (slow != fast) {
- slow = slow.next;
- fast = fast.next;
- }
-
- return slow;
- }
-
-
- //如果两个链表都无环,判断两链表是否相交,相交则返回第一个相交节点,不相交则返回null
- public static Node noLoop(Node head1, Node head2) {
- if (head1 == null || head2 == null) {
- return null;
- }
-
- int length1 = 0, length2 = 0;
- //遍历链表1
- while (head1.next != null) {//链表1在最后一个节点停
- length1++;
- head1 = head1.next;
- }
- //遍历链表2
- while (head2.next != null) {//链表2在最后一个节点停
- length2++;
- head2 = head2.next;
- }
-
- if (head1 == head2) {//不相交
- return null;
- } else {
- while (head1 != head2) {//还没相遇
- if (length1 > length2) {//链表1较长
- length1--;
- head1 = head1.next;
-
- } else if (length1 < length2) {//链表2较长
- length2--;
- head2 = head2.next;
-
- } else {//长链表先走了差值长度之后,两链表一起走直到相遇
- head1 = head1.next;
- head2 = head2.next;
- }
- }
- }
-
- return head1;
- }
-
-
- //如果两个链表都有环,判断两链表是否相交,相交则返回第一个相交节点,不相交则返回null
- //loop1 = getloopNode(head1); loop2 = getloopNode(head2);
- public static Node bothLoop(Node head1, Node head2, Node loop1, Node loop2) {
-
- if (loop1 == loop2) {//情况2
-
- int length1 = 0, length2 = 0;
- //遍历链表1
- while (head1.next != null) {//链表1在最后一个节点停
- length1++;
- head1 = head1.next;
- }
- //遍历链表2
- while (head2.next != null) {//链表2在最后一个节点停
- length2++;
- head2 = head2.next;
- }
-
- if (head1 == head2) {//不相交
- return null;
- } else {
- while (head1 != head2) {//还没相遇
- if (length1 > length2) {//链表1较长
- length1--;
- head1 = head1.next;
-
- } else if (length1 < length2) {//链表2较长
- length2--;
- head2 = head2.next;
-
- } else {//长链表先走了差值长度之后,两链表一起走直到相遇
- head1 = head1.next;
- head2 = head2.next;
- }
- }
- }
- return head1;
-
- } else {//情况1和情况3
-
- Node temp = loop1.next;
- while (temp != loop1) {//在圈里面遍历
-
- if (temp == loop2) {//遇到loop2,情况3
- return loop1;//return loop2;
- }
- temp = temp.next;
- }
- }
- return null;//情况1
- }
-
- public static Node getIntersectNode(Node head1,Node head2){
- if(head1 == null || head2 == null){
- return null;
- }
-
- Node loop1 = getloopNode(head1);
- Node loop2 = getloopNode(head2);
- if(loop1 == null && loop2 == null){
- return noLoop(head1,head2);
- } else if (loop1 != null && loop2 != null) {
- return bothLoop(head1,head2,loop1,loop2);
- }else{
- return null;
- }
- }
-
-
- }
-
-
-
-