单链表可能有环无环;
给定两个 单链表的头节点 head1和head2,这两个链表可能相交,也可能 不相交。请实现一个函数, 如果两个链表相交,请返回相交的 第一个节点;如果不相交,返回null 即可。
链表长度分别为 N M, 时间复杂度O(N + M);额外空间 O(1) ;
1 package my_basic.class_3; 2 3 public class FindFirstIntersectNode { 4 public static class Node{ 5 int value; 6 Node next; 7 public Node(int data) { 8 this.value = data; 9 } 10 } 11 /** 12 * 找到相交节点 13 * @return 14 */ 15 public static Node getIntersectNode(Node head1,Node head2) { 16 if (head1 == null || head2==null) { 17 return null; 18 } 19 //环节点 20 Node loop1 = getLoopNode(head1); 21 Node loop2 = getLoopNode(head2); 22 23 if (loop1 == null && loop2 == null) { 24 return getNoLoop(head1,head2); 25 } 26 if (loop1!=null && loop2!=null) { 27 return bothLoop(head1,loop1,head2,loop2); 28 } 29 return null; 30 31 } 32 33 //判断有没有环 如果有环 返回第一个入环节点 34 //第1种:hashset实现 35 //第2种:一个快指针 一个慢指针 ; 如果相遇了, 快指针从头开始 每次一步走,首次相遇的节点就是第一个入环节点 36 public static Node getLoopNode(Node head) { 37 //2. 38 if (head == null || head.next == null || head.next.next == null ) { 39 return null; 40 } 41 Node n1; //slow 42 Node n2; //fast 43 n1 = head.next; 44 n2 = head.next.next; 45 while(n1 != n2) { 46 if (n2.next == null || n2.next.next == null ) { 47 return null; 48 } 49 n1 = n1.next; 50 n2 = n2.next.next; 51 } 52 n2 = head; 53 while (n1 != n2) { 54 n1 = n1.next; 55 n2 = n2.next; 56 } 57 return n1; 58 59 //1. 需要额外的哈希表做辅助空间 60 /*HashSet<Object> set = new HashSet<>(); 61 Node n1 = head; 62 while (n1 != null) { 63 if (set.contains(n1)) { 64 return n1; 65 } 66 set.add(n1); 67 n1 = n1.next; 68 } 69 return null;*/ 70 } 71 72 //都没有环: 也可以借助hashset 73 public static Node getNoLoop(Node head1, Node head2) { 74 if (head1==null || head2 == null) { 75 return null; 76 } 77 Node cur1 = head1; //long list 78 Node cur2 = head2; //short list 79 int n=0; 80 while (cur1.next != null) { 81 n++; 82 cur1 = cur1.next; 83 } 84 while (cur2.next != null) { 85 n--; 86 cur2 = cur2.next; 87 } 88 if (cur1 != cur2) { 89 return null; 90 } 91 cur1 = n>0 ? head1 : head2; 92 cur2 = cur1 == head1 ? head2 : head1; 93 94 n = Math.abs(n); 95 while (n != 0) { 96 n--; 97 cur1 = cur1.next; 98 } 99 while (cur1 != cur2) { 100 cur1 = cur1.next; 101 cur2 = cur2.next; 102 } 103 return cur1; 104 } 105 106 //都有环: 也可以借助hashset 107 public static Node bothLoop(Node head1, Node loop1, Node head2, Node loop2) { 108 if (loop1 == loop2 ) { 109 Node cur1 = head1; //long 110 Node cur2 = head2; //short 111 int n=0; 112 while (cur1.next != loop1) { 113 n++; 114 cur1 = cur1.next; 115 } 116 while (cur2.next != loop2) { 117 n--; 118 cur2 = cur2.next; 119 } 120 if (cur1 != cur2) { 121 return null; 122 } 123 cur1 = n>0 ? head1 : head2; 124 cur2 = cur1 == head1 ? head2 : head1; 125 126 n = Math.abs(n); 127 while (n > 0) { 128 n--; 129 cur1 = cur1.next; 130 } 131 while (cur1 != cur2) { 132 cur1 = cur1.next; 133 cur2 = cur2.next; 134 } 135 return cur1; 136 }else{ 137 Node n = loop1.next; 138 while(n != loop1) { 139 if (n == loop2) { 140 return loop1; 141 } 142 n = n.next; 143 } 144 return null; 145 } 146 } 147 148 public static void main(String[] args) { 149 // 1->2->3->4->5->6->7->null 150 Node head1 = new Node(1); 151 // head1.next = new Node(2); 152 // head1.next.next = new Node(3); 153 // head1.next.next.next = new Node(4); 154 // head1.next.next.next.next = new Node(5); 155 // head1.next.next.next.next.next = new Node(6); 156 // head1.next.next.next.next.next.next = new Node(7); 157 // 158 // // 0->9->8->6->7->null 159 Node head2 = new Node(0); 160 // head2.next = new Node(9); 161 // head2.next.next = new Node(8); 162 // head2.next.next.next = head1.next.next.next.next.next; // 8->6 163 // System.out.println(getIntersectNode(head1, head2).value); 164 // 165 // 1->2->3->4->5->6->7->4... 166 head1 = new Node(1); 167 head1.next = new Node(2); 168 head1.next.next = new Node(3); 169 head1.next.next.next = new Node(4); 170 head1.next.next.next.next = new Node(5); 171 head1.next.next.next.next.next = new Node(6); 172 head1.next.next.next.next.next.next = new Node(7); 173 head1.next.next.next.next.next.next.next = head1.next.next.next; // 7->4 174 175 // // 0->9->8->2... 176 // head2 = new Node(0); 177 // head2.next = new Node(9); 178 // head2.next.next = new Node(8); 179 // head2.next.next.next = head1.next; // 8->2 180 // System.out.println(getIntersectNode(head1, head2).value); 181 182 // 0->9->8->6->4->5->6.. 183 head2 = new Node(0); 184 head2.next = new Node(9); 185 head2.next.next = new Node(8); 186 head2.next.next.next = head1.next.next.next.next.next; // 8->6 187 System.out.println(getIntersectNode(head1, head2).value); 188 189 } 190 }