编写一个程序,找到两个单链表相交的起始节点。
例如,下面的两个链表:
A: a1 → a2 ↘ c1 → c2 → c3 ↗ B: b1 → b2 → b3
在节点 c1 开始相交。
解题思路:
首先,我认为这题的题目描述不够完整。相交链表可能只是部分相交,并不一定是在c1点相交后,后面一直相交,可能也会产生分叉,可能在c3之后会有各自的尾巴,当然通过分析标准版的代码上看,题目默认只有实例指针情况。
1. 当后面没有各自的尾巴时:
可以先统计链表的长度lenA,lenB,更长的一个先往前移动abs(lenA-lenB)个结点。然后一起往后移动知道两个结点是一样的。如果没有,就返回空。当然这一步可以直接判断两个链表的末尾是否相等,避免重复遍历两个不想交的链表。
class Solution { public: ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) { if (headA == nullptr || headB == nullptr) return nullptr; auto it1 = headA, it2 = headB; int len1 = 1, len2 = 1; while (it1->next != nullptr) it1 = it1->next, ++len1; while (it2->next != nullptr) it2 = it2->next, ++len2; if (it1 != it2) return nullptr; if (len1 > len2) for (int i = 0; i != len1 - len2; ++i) headA = headA->next; else for (int i = 0; i != len2 - len1; ++i) headB = headB->next; int len = min(len1, len2); for (int i = 0; i != len; ++i) { if (headA == headB) return headA; headA = headA->next; headB = headB->next; } return nullptr; } }; |
2. 实际上,严格意义上来说,两个链表的初始相交位置,应该是一个链表的结点首次出现在另一个链表时候,所以用到hash。
class Solution { public: ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) { unordered_map<ListNode*, bool> mp_A, mp_B; while (headA || headB ) { if(headA) mp_A[headA] = true; if(headB) mp_B[headB] = true; if (mp_B[headA] == true) { return headA; } else mp_B.erase(headA); if (mp_A[headB] == true) { return headB; } else mp_A.erase(headB); if (headA) headA = headA->next; if (headB) headB = headB->next; } return NULL; } }; |