题目
解题代码初版
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
unordered_set<ListNode*> set;
ListNode* tmp1 = headA, * tmp2 = headB;
while(tmp1 != NULL){
set.insert(tmp1);
tmp1 = tmp1->next;
}
while(tmp2 != NULL){
if(set.find(tmp2) != set.end()) return tmp2;
tmp2 = tmp2->next;
}
return NULL;
}
};
解题思路
运用集合。
集合小特点:不能有重复的元素,无序。
- 遍历链表A,并存入set中。
- 遍历链表B,边遍历边在set中查找是否有相同的元素。
语法点
集合的定义
unordered_set<ListNode*> set;
集合的插入
set.insert(tmp1);
集合的find()函数
if(set.find(tmp2) != set.end()) return tmp2;
集合的count()函数
// 由于集合的count只能取1和0,因此可以用来判断是否有相同元素。
//(用来查找set中某个某个键值出现的次数。这个函数在set并不是很实用,因为一个键值在set只可能出现0或1次,这样就变成了判断某一键值是否在set出现过了。)
if(set.count(hB) == 1) return hB;
别人的解法(优化)
作者:腐烂的橘子
我们使用两个指针 node1,node2 分别指向两个链表 headA,headB 的头结点,然后同时分别逐结点遍历,当 node1 到达链表 headA 的末尾时,重新定位到链表 headB 的头结点;当 node2 到达链表 headB 的末尾时,重新定位到链表 headA 的头结点。
这样,当它们相遇时,所指向的结点就是第一个公共结点。
注意点
- 两个链表长度分别为L1+C、L2+C, C为公共部分的长度,按照楼主的做法: 第一个人走了L1+C步后,回到第二个人起点走L2步;第2个人走了L2+C步后,回到第一个人起点走L1步。 当两个人走的步数都为L1+L2+C时就两个家伙就相爱了)
- 两链表不相交时,由于行程一样长,最终会同时走到对方链表的终点,同时出现null,此时满足pA = pB循环终止
- 语法nullptr
C++ 98标准期间,用NULL
C++11 标准期间,用nullptr,专用于初始化空类型指针
总之在 C++11 标准下,相比 NULL 和 0,使用 nullptr 初始化空指针可以令我们编写的程序更加健壮。
也就是说nullptr是后来。
- 语法
node1 = node1 != NULL ? node1->next : headB;
如果node1不为空,则执行node1->next;
如果node1为空,则执行headB
动图可访问下面链接:https://leetcode-cn.com/problems/liang-ge-lian-biao-de-di-yi-ge-gong-gong-jie-dian-lcof/solution/shuang-zhi-zhen-fa-lang-man-xiang-yu-by-ml-zimingm/
代码
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode *node1 = headA;
ListNode *node2 = headB;
while (node1 != node2) {
node1 = node1 != NULL ? node1->next : headB;
node2 = node2 != NULL ? node2->next : headA;
}
return node1;
}
};