题目描述
输入两个链表,找出它们的第一个公共结点。
有下面三种思路:
1. 设置两个指针,同时向后走,到当前链表的尾节点时,指向另一个链表,
则必然在公共点相遇 或 通时走到对方的尾节点, 因为 X + Y +Z = Z + Y + X 或 X + Y = Y + X
2. 使用map保存第一个链表的节点,然后遍历第二个链表,在map中查找是否存在
3. 先分别计算两个链表的长度, 计算长度差, 让较长的链表先走差值,然后再同时走, 则必然在公共点相遇 或 同时到尾节点
代码如下:
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
//方法一: 两个指针同时向后走,到尾节点时换到另一个链表
// 如果有公共点 则必然在交换后,相遇
// 如果没有公共点 则都走到对方的尾节点后 同时为NULL
ListNode* find_first_common_node_change_pointer(ListNode* pHead1, ListNode* pHead2){
ListNode* p1 = pHead1;
ListNode* p2 = pHead2;
while(p1 != p2)
{
p1 = (NULL == p1) ? pHead2 : p1->next;
p2 = (NULL == p2) ? pHead1 : p2->next;
}
return p1;
}
//方法二:使用map保存第一个链表的节点 再另一个链表中查找
ListNode* find_first_common_node_map(ListNode* pHead1, ListNode* pHead2){
map<ListNode*, ListNode*> nodemap;
ListNode* p1 = pHead1;
ListNode* p2 = pHead2;
while(p1){
nodemap[p1] = NULL;
p1 = p1->next;
}
while(p2){
if(nodemap.find(p2) != nodemap.end()){
return p2;
}
p2 = p2->next;
}
return NULL;
}
int get_list_length(ListNode* head){
int length = 0;
ListNode* p = head;
while(p){
length++;
p = p->next;
}
return length;
}
//方法三:计算两个链表的长度,让较长的一个先走 差值,然后同时走,比然在公共点相遇
ListNode* find_first_common_node_length(ListNode* pHead1, ListNode* pHead2){
ListNode* p1 = pHead1;
ListNode* p2 = pHead2;
int length1 = get_list_length(pHead1); //先分别计算链表的长度
int length2 = get_list_length(pHead2);
ListNode* longer = length1 > length2 ? pHead1 : pHead2;
ListNode* shorter = length1 > length2 ? pHead2 : pHead1;
int diff = length1 > length2 ? length1 - length2 : length2 - length1; //计算长度差值
while(diff){ //较长的先走diff步
longer = longer->next;
diff--;
}
while(longer != shorter){ //然后同时走 必然相遇或同时走到尾
longer = longer->next;
shorter = shorter->next;
}
return longer;
}
ListNode* FindFirstCommonNode(ListNode* pHead1, ListNode* pHead2) {
//return find_first_common_node_change_pointer(pHead1, pHead2);
//return find_first_common_node_map(pHead1, pHead2);
return find_first_common_node_length(pHead1, pHead2);
}
};