给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。
图示两个链表在节点 c1 开始相交:
题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
示例 1:
示例 2:
示例 3:
提示:
进阶:你能否设计一个时间复杂度 O(n) 、仅用 O(1) 内存的解决方案?
这道题我认为最简单易懂的就是哈希法,我们将headA的节点全部遍历进一个unordered_set中,然后再拿headB的节点一一去与存储在head中的节点去做对比,如果找到了,就直接返回。
简直太好懂了,之前我的思维一种困在如果对比节点数据相同的个数上,但节点数据相等不等于两个链表有相交的地方啊。看了哈希法后豁然开朗,直接对比节点就行了,下面请看代码:
class Solution {
public:ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {unordered_set set;ListNode* pos = headA;while(pos){set.insert(pos);pos = pos->next;}pos = headB;while(pos){if(set.count(pos)) return pos;pos = pos->next;}return nullptr;}
};
复杂度分析:
时间复杂度为O(m+n),其中m是链表headA的节点数,n是链表b的节点数,我们需要各遍历两个链表一次。
空间复杂度为O(m),其中m是链表headA的节点数,我们只需要将A的元素添加进集合即可
题目开始的时候其实就已经明确的告诉过我们:保证题解中链表不会成环。所以不用去考虑链表成环问题。
这道题你仔细去看会发现一个规律,我们设置两个指针p1,p2,分别从链表headA,headB的开头开始遍历,p1遍历完a就去遍历b,同样p2遍历完b就去遍历a。如果,两个链表是相交的,则p1,p2,在变量的过程中,一定有一次会相等,反之,到变量结束都不相等。
这个规律你自己试一下就好了,不必去在乎数学的什么公式呀,其他的,心灵自然通畅,下面请看代码:
class Solution {
public:ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {ListNode* p1 = headA;ListNode* p2 = headB;while(p1 || p2){if(p1 == p2) return p1;if(!p1) p1 = headB;else p1 = p1->next;if(!p2) p2 = headA;else p2 = p2->next;}return nullptr;}
};
复杂度分析:
时间复杂度:O(m+n),m是链表A的节点个数,n是链表B的节点个数,我们需要遍历链表A,B各一次。
空间复杂度:O(1),我们没有使用额外的数据结构,只是设置了几个变量,所以是O(1)
所谓的遍历长度法就是,先各自遍历各自的链表一遍,统计出两个链表的节点个数。然后再设置2个指针,短的那个链表先走两个链表节点差的步数,然后再一起走,去比较节点。相同则返回该节点,否则返回nullptr。
这种方法其实也很简单直接,我就不给出代码了。自己去试试看吧。这也是种思路。
我们在比较两个链表是否相交的时候,不要去陷入一个思维误区,就是拿节点的val去做对比,而是拿节点本身去做对比。想明白这点后,再仔细观察一下,就能够得出答案。这道题说实话不算难题,但需要小小思考一下。