问题
编写一个程序,找到两个单链表相交的起始节点。 如下面的两个链表:
graph LR a1 --> a2 b1 --> b2 --> b3 a2 --> c1 b3 --> c1 c1 --> c2 --> c3
在节点开始相交。 示例 1:
graph LR a1[4] --> a2[1] b1[5] --> b2[0] --> b3[1] a2 --> c1[8] b3 --> c1 c1 --> c2[4] --> c3[5]
输入: intersectVal = 8, listA = , listB = , skipA = 2, skipB = 3 输出: Reference of the node with value = 8 输入解释: 相交节点的值为 (注意,如果两个列表相交则不能为 )。从各自的表头开始算起,链表 A 为 ,链表 B 为 。在 A 中,相交节点前有个节点;在 B 中,相交节点前有个节点。
示例 2:
graph LR a1[0] --> a2[9] --> a3[1] b1[3] a3 --> c1[2] b1 --> c1 c1 --> c2[4]
输入: intersectVal = 2, listA = , listB = , skipA = 3, skipB = 1 输出: Reference of the node with value = 2 输入解释: 相交节点的值为 (注意,如果两个列表相交则不能为 )。从各自的表头开始算起,链表 A 为 ,链表 B 为 。在 A 中,相交节点前有 个节点;在 B 中,相交节点前有 个节点。
示例 3:
graph LR a1[2] --> a2[6] --> a3[4] b1[1] --> b2[5]
输入: intersectVal = 0, listA = , listB = , skipA = 3, skipB = 2 输出: null 输入解释: 从各自的表头开始算起,链表 A 为 ,链表 B 为 。由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。 解释: 这两个链表不相交,因此返回 null。
注意:
- 如果两个链表没有交点,返回 null.
- 在返回结果后,两个链表仍须保持原有的结构。
- 可假定整个链表结构中没有循环。
- 程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存。
解法
注意到这样一个事实,如果两个链表相交,那么在相交节点前面的两个分叉上,正好相差这两个链表长度之差的元素个数。因此,首先遍历两个链表,得到链表长度,然后长度更长的链表先往前走长度之差的步数,然后后面两个链表向前推进到相等即为结果。
代码
java
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if (headA == null || headB == null) {
return null;
}
//首先遍历两个链表查询长度
int l1 = 0;
ListNode h1 = headA;
while (h1 != null) {
h1 = h1.next;
l1++;
}
int l2 = 0;
ListNode h2 = headB;
while (h2 != null) {
h2 = h2.next;
l2++;
}
//长度更长的那个需要先走几步,直到两个长度相等时才同时前进。
h1 = headA;
h2 = headB;
int dif = l1-l2;
if (dif > 0) {
while(dif-- >0) {
h1 = h1.next;
}
} else if (dif < 0) {
while(dif++ < 0) {
h2 = h2.next;
}
}
int len = Math.min(l1, l2);
while (h1 != h2){
h1 = h1.next;
h2 = h2.next;
}
return h1;
}
}