「这是我参与2022首次更文挑战的第26天,活动详情查看:2022首次更文挑战」。
题目描述
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。
图示两个链表在节点 c1 开始相交:
题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
思路分析
从前往后自然很难找到相交的节点,除非用n^2的时间复杂度遍历。但是相交的节点以后所有的节点都会相同,因此我们可以想到如果从后往前来看的话,是不是就可以找到了相交节点。
- 从后往前,并且声明两个栈,不断遍历将元素写入栈中
- 不断将栈中元素弹出,直到栈1和栈2弹出的节点不同时,找到上一个被弹出的节点。
主要代码如下:
while (!(stk1.empty() || stk2.empty())){
ListNode* idx1 = stk1.top();stk1.pop();
ListNode* idx2 = stk2.top();stk2.pop();
if(idx1 -> val != idx2 -> val){
if(pre == nullptr)return nullptr;
cout << pre ->val << endl;
return pre;
}
pre = idx1;
}
然而这个方法过不去力扣。。
不过之前做过环形链表的判断倒是给了些优化的灵感,如果两个有相交点,那么可以将A分为Apre,common两部分,将B分为Bpre,common两部分,我们分别设置headA,headB作为起点,只需要让两边都走过
的长度,就可以让两者相遇。
具体实现
while (tmpA != tmpB) {
tmpA = tmpA->next;
tmpB = tmpB->next;
if(tmpA == nullptr){
tmpA = headB;
}
if(tmpB == nullptr){
tmpB = headA;
}
}
核心代码如上
总结
第一个方法的时间复杂度是O(n),但空间复杂度也是O(n).而第二种时间复杂度不变的同时,空间复杂度确实O(1)。大大节省了空间消耗。