题目
编写一个程序,找到两个单链表相交的起始节点。
如下面的两个链表:
在结点c1开始相交
题目链接
示例
输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
输出:Reference of the node with value = 8
输入解释:相交节点的值为 8 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
题目分析
借鉴官方题解评论区一位楼主的创意,这道题的算法我称之为“浪漫算法”——对的人总会相交。
所谓“浪漫算法”,就是用两个指针分别遍历两个链表。如果第一个指针遍历完,则让其指向headB
;如果第二个指针遍历完,则让其指向headA
;如果两个指针相等,则遍历结束,返回这个指针。
在这里简单验证一下方法有效性,令headA
长度为m,headB
长度为n,那么遍历次数最多为m+n。如果两个链表有相交的部分,按照上面的方法遍历,两个指针一定在同一个位置停止遍历。
举例说明:
listA = [4,1,8,4,5], listB = [5,0,1,8,4,5]
令p1 = listA
,p2 = listB
同时遍历p1和p2
- p1 = 4, p2 = 5
- p1 = 1, p2 = 0
- p1 = 8, p2 = 1
- p1 = 4, p2 = 8
- p1 = 5, p2 = 4
- p1 = listB = 5, p2 = 5
- p1 = 0, p2 = listA = 4
- p1 = 1, p2 = 1
- p1 = 8, p2 = 8,相遇了
typedef struct ListNode* list;
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
if (headB == NULL || headA == NULL) return 0;
list p1, p2;
p1 = headA;
p2 = headB;
while (p1 != p2){
if (p1 == NULL){
p1 = headB;
}else {
p1 = p1->next;
}
if (p2 == NULL){
p2 = headA;
}else {
p2 = p2->next;
}
}
if (p1 == NULL) return 0;
else return p1;
}