剑指offer - 36两个链表的第一个公共结点

题目描述

输入两个链表,找出它们的第一个公共结点。

有下面三种思路:

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);
    }
};

    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值