0.题目
编写一个程序,找到两个单链表相交的起始节点。
注意:
* 如果两个链表没有交点,返回 null.
* 在返回结果后,两个链表仍须保持原有的结构。
* 可假定整个链表结构中没有循环。
* 程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存。
1.分析
相交的概念
相交的概念,不是两条直线相交与一个焦点;而是因为链表带有next指针,所以一旦有一个焦点,那么往后的节点都是指向同一个节点。
因此,如果两个链表长度相等,那么直接往后遍历,如果有相等的node节点,那么一定会相交;否则不想交;
如果两个链表长度不相等,那么需要消除长短链表的长度差再同时往后遍历即可;
所以此题的关键在于,如何消长短链表的长度差?
消除长度差
常规法
或许可以这么做:
分别遍历两个链表,统计链表长度,找到长度差K,然后长链表先走K步,之后短链表与之同行再判断。这种做法没问题,相对来讲比较复杂。
高阶法
比较高阶一点的做法就是长短链表相加消除长度差。
如下图所示:
长链表A长度为5,短链表B长度为4;可以把两个链表拼接长一个链表,只是顺序不同;
那么两个相同长度的链表,同时往后遍历节点,那么一定会走到相交的节点。
- 注意:A链表的第三个节点和B链表的第二个节点并不是相交节点,因为节点对象存储地址不同,不能单纯的根据节点的value值判断。
2.解法: 链表相加 1ms 41.4MB
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode nodeA = headA;
ListNode nodeB = headB;
while (nodeA != nodeB) {
nodeA = nodeA != null ? nodeA.next : headB;
nodeB = nodeB != null ? nodeB.next : headA;
}
return nodeA;
}
如果看懂分析部分,那么代码理解不难。
这里注意,nodeA遍历到headA链表的末尾,那么nodeA会指向headB,从而继续走nodeA.next。