记录新手小白做题历程。
题目
题目:
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。
图示两个链表在节点 c1 开始相交:
保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
尝试:
思路:暴力解法,两个循环,一个记录A链的数字,一个移动B链的数字,若两个结点的数字相同,则判断后面的数字是否相同,直至遇见结点。
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode *p1=headA;
ListNode *p2=headB;
int i=0,j=0;
for(;p1;i++){
int count=p1->val;//记录p1结点的值
for(;p2;j++){
if(count==p2->val){//找到了相同数值的结点,判断后面的链表是否相等
ListNode *cur=p2->next;
ListNode *cur1=p1->next;
while(cur){
if(cur->val!=cur1->val){
break;
}
cur=cur->next;
cur1=cur1->next;
}
if(cur==nullptr&&cur1==nullptr)
return p2->val;//如果,它们一直交到最后一个结点,找到了
}
p2=p2->next;
}
p1=p1->next;
p2=headB;//初始化p2
}
return null;
}
};
代码写出来后显示编译错误。
1.cannot initialize return object of type 'ListNode *' with an lvalue of type 'int' return p2->val
无法初始化类型为 'ListNode *' 的返回对象,左值类型为 'int' 返回 p2->val
大概意思是说,需要我返回结点但我返回成了Int整型
2.use of undeclared identifier 'null' return null; 使用未声明的标识符"null"返回空
这个返回null是看题解里写的,正确应该是返回nullptr
好了改正之后进行提交,对了44个,错一个。
我不是很理解自己哪个方向出错了,如果这个错了,那其它的不应该对啊,怎么会跳过1 呢
看下别人代码。
正确答案
官方题解。
lenA, lenB。设重合长度为c。设两者节点总和为sum。设实际总结点数为z。
- 若有重合,sum! = z
应该有lenA+lenB = sum=z + c;//一个很简单的论证题应该可以想明白的,c被重合了。
双指针遍历时,如果两者有重合点,一定都会走到sum的时候,这个时候正好走到还差C长度的节点上,即sum != z;
- 若不重合,sum = z;,两个节点都走到空
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode *A = headA, *B = headB;
while (A != B) {
A = A != nullptr ? A->next : headB;//遍历A,A是否等于空。为空就继续遍历B,不为空则继续遍历
B = B != nullptr ? B->next : headA;//遍历B,与上面一行相似
}
return A;
}
};
看到这个代码量瑟瑟发抖 。
一个指针先遍历A,再遍历B,另一个指针先遍历B,再遍历A,若两者最终相等了,说明两者有交点,若两者最终都没有就是空,不过这个也符合最后返回A的条件,因为A最后遍历为空。
great,真的很棒。
第二位大佬:
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode* curA = headA;
ListNode* curB = headB;
int lenA = 0, lenB = 0;
while (curA != NULL) { // 求链表A的长度
lenA++;
curA = curA->next;
}
while (curB != NULL) { // 求链表B的长度
lenB++;
curB = curB->next;
}
curA = headA;
curB = headB;
// 让curA为最长链表的头,lenA为其长度
if (lenB > lenA) {
swap (lenA, lenB);
swap (curA, curB);
}
// 求长度差
int gap = lenA - lenB;
// 让curA和curB在同一起点上(末尾位置对齐)
while (gap--) {
curA = curA->next;
}
// 遍历curA 和 curB,遇到相同则直接返回
while (curA != NULL) {
if (curA == curB) {
return curA;
}
curA = curA->next;
curB = curB->next;
}
return NULL;
}
};
他的写法非常巧妙,在将两个链表取到长度一致的情况下之后,后面若遇到相同的数字则合为同一链表。
不过我觉得不一定啊,遇到一个相同的后面不一定就合成一个链表了。
看来这道题还要再研究研究。