单链表之两链表相交的第一个公共节点

时间:2023-02-11 11:02:08

两链表相交的第一个公共节点:
题目描述:如果两个无环单链表相交,怎么求出他们相交的第一个节点呢?
  分析:采用对齐的思想。计算两个链表的长度 L1 , L2,分别用两个指针 p1 , p2 指向两个链表的头,然后将较长链表的 p1(假设为 p1)向后移动L2 - L1个节点,然后再同时向后移动p1 , p2,直到 p1 = p2。相遇的点就是相交的第一个节点。

 1 /**
2 * 求两个单链表相交的第一个节点 对第一个链表遍历,计算长度len1,同时保存最后一个节点的地址。
3 * 对第二个链表遍历,计算长度len2,同时检查最后一个节点是否和第一个链表的最后一个节点相同,若不相同,不相交,结束。
4 * 两个链表均从头节点开始,假设len1大于len2
5 * ,那么将第一个链表先遍历len1-len2个节点,此时两个链表当前节点到第一个相交节点的距离就相等了,然后一起向后遍历,直到两个节点的地址相同。
6 * 时间复杂度,O(len1+len2)
7 *
8 * ---- len2 |__________ | --------- len1 |---|<- len1-len2
9 */
10 public static Node getFirstCommonNode(Node head1, Node head2) {
11 if (head1 == null || head2 == null) {
12 return null;
13 }
14 // 求链表1的长度
15 int len1 = 1;// 初始值一定是1
16 Node tail1 = head1;
17 while (tail1.next != null) {
18 tail1 = tail1.next;
19 len1++;
20 }
21 // 求链表2的长度
22 int len2 = 1;
23 Node tail2 = head2;
24 while (tail2.next != null) {
25 tail2 = tail2.next;
26 len2++;
27 }
28
29 // 不相交直接返回NULL
30 // 还记得前面用尾指针是否相等来判断相交吗
31 if (tail1 != tail2) {
32 return null;
33 }
34
35 Node n1 = head1;
36 Node n2 = head2;
37
38 // 略过较长链表多余的部分
39 // 执行完成之后,两个指针距离相交的第一个结点的距离相等
40 if (len1 > len2) {
41 int k = len1 - len2;
42 while (k != 0) {
43 n1 = n1.next;
44 k--;
45 }
46 } else {
47 int k = len2 - len1;
48 while (k != 0) {
49 n2 = n2.next;
50 k--;
51 }
52 }
53
54 // 一起向后遍历,直到找到交点
55 while (n1 != n2) {
56 n1 = n1.next;
57 n2 = n2.next;
58 }
59 // 循环结束之后,n1=n2
60 return n1;
61 }