题目:
Write a program to find the node at which the intersection of two singly linked lists begins.
For example, the following two linked lists:A: a1 → a2 ↘ c1 → c2 → c3 ↗ B: b1 → b2 → b3 begin to intersect at node c1.
Notes:
If the two linked lists have no intersection at all, returnnull
.
The linked lists must retain their original structure after the function returns.
You may assume there are no cycles anywhere in the entire linked structure.
Your code should preferably run in O(n) time and use only O(1) memory.
解释:
寻找两个链表的交点。
解法1:
分别遍历两个链表,得到分别对应的长度。然后求长度的差值,把较长的那个链表向后移动这个差值的个数,然后一一比较即可。(因为要先求链表的长度,所以速度较慢)
python代码:
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def getIntersectionNode(self, headA, headB):
"""
:type head1, head1: ListNode
:rtype: ListNode
"""
if not headA or not headB:
return None
def listLen(head):
p=head
length=0
while p!=None:
length+=1
p=p.next
return length
lenA=listLen(headA)
lenB=listLen(headB)
lenDif=lenA-lenB
longList,shortList=headA,headB
if lenB>lenA:
lenDif=lenB-lenA
longList,shortList=headB,headA
i=0
while i<lenDif:
longList=longList.next
i+=1
while longList and shortList and longList!=shortList:
longList=longList.next
shortList=shortList.next
return longList
解法2:(更通用的解法)
可以用环的思想来做(为啥是环的思想?当调到另一个链表的头部的时候就是“接上环”的过程),让两条链表分别从各自的开头开始往后遍历,当其中一条遍历到末尾时,我们跳到另一个条链表的开头继续遍历。两个指针最终会相等,而且只有两种情况:
1.在交点处相遇
2.在各自的末尾的空节点处相等(一定要指到链尾的空结点再停止哦,不要指到最后一个结点就停止~)。
因为两个指针走过的路程相同:
如果两个链表不重叠,则走过的路程长度是两个链表的长度之和
如果两个链表重叠,则走过的路程长度是重叠区域长度加上两个不重叠区域的长度,所以一定会相等。
证明:
设 A
的长度为 a + c
, B
的长度为 b + c
,其中 c
为尾部公共部分长度,可知 a + c + b= b + c + a
。
当访问 A
链表的指针访问到链表尾部时,令它从链表B
的头部开始访问链表 B
;同样地,当访问 B
链表的指针访问到链表尾部时,令它从链表 A
的头部开始访问链表 A
。这样就能控制访问 A
和 B
两个链表的指针能同时访问到交点。
python代码:
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
#解法2
class Solution(object):
def getIntersectionNode(self, headA, headB):
"""
:type head1, head1: ListNode
:rtype: ListNode
"""
tempA,tempB=headA,headB
while tempA!=tempB:
tempA=tempA.next if tempA else headB
tempB=tempB.next if tempB else headA
return tempA
c++代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode* tmpA=headA;
ListNode* tmpB=headB;
while(tmpA!=tmpB)
{
tmpA=tmpA?tmpA->next:headB;
tmpB=tmpB?tmpB->next:headA;
}
return tmpA;
}
};
总结: