【剑指offer】链表——036 两个链表的第一个公共结点


在这里插入图片描述


036 两个链表的第一个公共结点

题目内容

输入两个链表,找出它们的第一个公共结点。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)

题目分析

这道题的难度在于理解清楚题意,链表的结点时这样定义的:

struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};

所以,作为公共结点,不应该只是value值相等,next指针指向的结点也应该相同,next指向的结点相同,也就是公共结点以后的结点都一样。用图来表示可能就是一个“Y”型的链表。
在这里插入图片描述

解题

解法一

双指针法。思路来源于牛客网的lizo大佬,假设有两个链表{A, B, C, D, X, Y, Z},长度为7;{E, F, X, Y, Z},长度为5,定义两个指针分别指向两个链表的头结点,链表1比链表2长两个结点,因为之前分析说了,公共结点以后的结点全部相同,那么链表1的指针先走两步,然后两个指针一起走,如果有一样的指针即为第一个公共结点。

代码

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
            val(x), next(NULL) {
    }
};*/
class Solution {
public:
    ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
        if(pHead1 == NULL || pHead2 == NULL)
            return NULL;
        int length1 = 0;
        int length2 = 0;
        ListNode* currpNode1 = pHead1;
        ListNode* currpNode2 = pHead2;
        while(currpNode1 != NULL){
            length1++;
            currpNode1 = currpNode1->next;
        }
        while(currpNode2 != NULL){
            length2++;
            currpNode2 = currpNode2->next;
        }
        currpNode1 = pHead1;
        currpNode2 = pHead2;
        if(length1 > length2){
            int step = length1 - length2;
            while(step){
                currpNode1 = currpNode1->next;
                step--;
            }
        }else{
            int step = length2 - length1;
            while(step){
                currpNode2 = currpNode2->next;
                step--;
            }
        }
        while(currpNode1 != NULL){
            if(currpNode1 == currpNode2)
                break;
            currpNode1 = currpNode1->next;
            currpNode2 = currpNode2->next;
        }
        return currpNode1;
    }
};

解法二

思路来源于一叶浮尘大佬,还是解法一中的例子,我们把它们接到一起,那么就变成了:

  • 链表1:{A, B, C, D, X, Y, Z, null, E, F, X, Y, Z, null}
  • 链表2:{E, F, X, Y, Z, null, A, B, C, D, X, Y, Z, null}

可以很直观的看到同时遍历,最后可以找到第一个公共结点X。

代码

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
            val(x), next(NULL) {
    }
};*/
class Solution {
public:
    ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
        if(pHead1 == NULL || pHead2 == NULL)
            return NULL;
        ListNode* currpNode1 = pHead1;
        ListNode* currpNode2 = pHead2;
        while(currpNode1 != NULL || currpNode2 != NULL){
            if(currpNode1 != currpNode2){
                if(currpNode1 == NULL)
                    currpNode1 = pHead2;
                else
                    currpNode1 = currpNode1->next;
                if(currpNode2 == NULL)
                    currpNode2 = pHead1;
                else
                    currpNode2 = currpNode2->next;
            }else{
                break;
            }
        }
        return currpNode1;
    }
};

以上思路为个人想法和网络各位大佬的题解的结合,欢迎讨论与指正。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值