题目描述
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。
图示两个链表在节点 c1 开始相交:
题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
解题思路
若两个无环单链表相交,则从交点开始,往后的每个结点均是共享结点,这是因为链表的next指针都是指向下一个元素的内存地址而非元素值。在单链表结构中,每个结点只有一个next指针,故每个结点都有且仅有唯一的下地址,那么不难发现,从相交结点开始,每个元素都只指向一个下地址,也就不会造成下图的X型相交情况。
具体步骤如下:
- 空链表与任意链表都不相交
- 若两个链表均为非空链表,由于从相交结点开始,此后两链表的结点数相等,所以,为了操作简便,我们可以让这两个长度未知的链表从距离相交结点相同距离的地方开始一起遍历
- 遍历求出两个链表的长度为lenA和lenB
- 求出两链表长度后,可知两链表指针均已到达链尾,这时我们可以判断出一种情况:如果两链表的链尾没指向同一个地址,这两个链表一定不相交
- 若链表相交,重新从头结点出发,让更长的那个链表先从头结点开始走|lenA-lenB|个长度,这就保证了两个链表能同时指向步骤2描述的位置,之后让两个链表每次同步向前走,当出现相同地址的时候,返回
/**
* 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;
ListNode nodeA = headA;
ListNode nodeB = headB;
int lenA = 0, lenB = 0;
while(nodeA.next != null) {
lenA ++;
nodeA = nodeA.next;
}
while(nodeB.next != null) {
lenB ++;
nodeB = nodeB.next;
}
if(nodeA != nodeB) return null;
nodeA = (lenA - lenB) >= 0 ? headA : headB;
nodeB = nodeA == headA ? headB : headA;
int skip = Math.abs(lenA - lenB);
while(skip != 0) {
skip --;
nodeA = nodeA.next;
}
while(nodeA != nodeB) {
nodeA = nodeA.next;
nodeB = nodeB.next;
}
return nodeA;
}
}