解法1:长链表先走,然后齐头并进
int countLen(struct ListNode *head) {
if (head == NULL)
return 0;
int cnt = 0;
while (head) {
cnt++;
head = head->next;
}
return cnt;
}
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
if (headA == NULL || headB == NULL)
return NULL;
int lenA = countLen(headA), lenB = countLen(headB);
struct ListNode *aPtr = headA, *bPtr = headB;
if (lenA > lenB) { //长链表先走
int diff = lenA - lenB;
while (diff--)
aPtr = aPtr->next;
} else if (lenA < lenB) {
int diff = lenB - lenA;
while (diff--)
bPtr = bPtr->next;
}
while (aPtr != bPtr) { //齐头并进
aPtr = aPtr->next;
bPtr = bPtr->next;
}
return aPtr;
}
解法2:每个指针走一遍两个链表,最后一定在公共节点相遇
如图1,两个链表的公共节点如绿线所示。如图二,指向两链表的指针遍历节点,若所指链表遍历完则转向另一个链表遍历,最后两指针会在第二遍遍历公共节点的时候相遇。若两链表没有公共节点,则绿色代表空指针。
图1:有交叉链表几何图示 图2:指针路线走势图
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
if (headA == NULL || headB == NULL)
return NULL;
struct ListNode *aPtr = headA, *bPtr = headB;
while (aPtr || bPtr) { //比aPtr != NULL|| bPtr != NULL更快
if (aPtr == NULL)
aPtr = headB;
if (bPtr == NULL)
bPtr = headA;
if (aPtr == bPtr) //命中注定的相遇
return aPtr;
aPtr = aPtr->next;
bPtr = bPtr->next;
}
return NULL;
}
解法2的while可以优化一下,具体可参考程序如下:
注:while的条件和返回值都不一样了。
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if (headA == NULL || headB == NULL)
return NULL;
ListNode *ptr1 = headA, *ptr2 = headB;
while (ptr1 != ptr2) {
if (ptr1 == NULL)
ptr1 = headB;
else
ptr1 = ptr1->next;
if (ptr2 == NULL)
ptr2 = headA;
else
ptr2 = ptr2->next;
}
return ptr1;
}
};