题目
给你两个单链表的头节点
headA
和headB
,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回null
。题目数据保证整个链式结构中不存在环。注意,函数返回结果后,链表必须保持其原始结构。
题解
判断两个单链表是否相交,只能通过依次比较结点的地址来判断,不能通过结点的值判断。首先,我们应该明确如果两个单链表相交,那么这两个链表的形状只能是Y字型,不能是X字型,如果是X字型,则相交结点有两个后继结点,而单链表结点只能有一个后继结点。因此可得出,若两个单链表相交,则两个链表的尾结点的地址一定相同;若两个链表的尾结点的地址不相同,则两个单链表一定不相交。
所以程序可以先判断两个链表尾结点的地址是否相同,若不同返回NULL;若相同则找相交结点。寻找相交结点的方法如下:
假设两个单链表的长度分别为lenA和lenB,设置两个指针分别指向两个链表的头结点,让指向较长链表的指针先走abs(lenA-lenB)步,然后两个指针再同时向后走,边走边比较指针所指结点的地址是否相等,若相等则返回当前结点,若不等则同时向后走一步,直到找到第一个相交结点为止。
代码如下:
struct ListNode* getIntersectionNode(struct ListNode* headA, struct ListNode* headB) { struct ListNode* tailA = headA; struct ListNode* tailB = headB; int lenA = 1; int lenB = 1; while (tailA->next) { tailA = tailA->next; lenA++; } while (tailB->next) { tailB = tailB->next; lenB++; } if (tailA != tailB) return NULL; struct ListNode* longList = headA; struct ListNode* shortList = headB; if (lenA < lenB) { longList = headB; shortList = headA; } int gap = abs(lenA - lenB); while (gap--) { longList = longList->next; } while (longList != shortList) { longList = longList->next; shortList = shortList->next; } return longList; }
注意,因为题目中说明链表中结点个数大于等于1,所以没有讨论空链表的情况。