题目:输入两个链表,返回两者的第一个公共节点
如上图,根据链表的结构,可以看出当两个当链表交汇后,之后的所有节点都肯定会一样。
所以第一个问题就要先确定输入的两个链表是否存在公共节点。可以分别遍历链表到末尾,如果两个尾节点一样,可以确认存在公共节点,否则一定不存在。
接下来需要确认公共节点的位置,容易看出如果两个链表长度一样的话,那么声明两个分别指向两个链表的头指针,以同样速度遍历链表,当两者首次相等时,即找到链表公共节点。
如果链表长度不一致怎么办呢?其实也很简单,第一次遍历的时候我们就已经可以确认链表长度。对于长的那个链表,比如上图的链表1-2-3,比4-5多1个节点,那么指向可以令1-2-3那个链表的指针先移动1个节点,之后可以认为节点2和节点4之后的链表长度一样了。之后同时前进两个节点后,在节点6获得相同节点。
代码如下:
ListNode* FirstCommonNodesInLists(LinkList a, LinkList b){
if(a==nullptr||b==nullptr) return nullptr;
int LenA = 0;
int LenB = 0;
ListNode *NodeA = a;
ListNode *NodeB = b;
while(NodeA!=nullptr){
LenA++;
NodeA = NodeA->Next;
}
while(NodeB!=nullptr){
LenB++;
NodeB = NodeB->Next;
}
if(NodeA!=NodeB) return nullptr;//如果两者尾指针不相等,则肯定没有共同节点
NodeA = a; NodeB = b;
//节点数多的先走,直到两个指针之后的链表长度一致
int step = abs(LenA - LenB);
if(LenA >= LenB) for(int i = 0; i < step; ++i) NodeA = NodeA->Next;
else for(int i = 0; i < step; ++i) NodeB = NodeB->Next;
while(NodeA!=NodeB&&NodeA!=nullptr){
NodeA = NodeA->Next;
NodeB = NodeB->Next;
}
return NodeA;//如果空,则表明无共同节点,否则返回第一个共同节点
}
其他思路
本题还有其他思路,我们可以很容易从头到尾遍历两个链表,如果两者尾指针相等,则确定有公共节点。此时只要想办法让两个链表的指针往回走,直到找到最后一个相同的节点即为公共节点。
由于链表只能单向遍历,要想往前比较,就需要用到栈。申请两个栈空间,遍历链表的同时将链表节点放进栈,遍历完成后比较栈顶元素,如果相等则弹出。直至两者不相等为止。
本题代码放在这里