37 - 两个链表的第一个公共节点

题目描述:

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

如:第一个公共节点为值为 6 的节点.



相关题型:在二叉树中找出两个节点的最低公共祖父节点。使用的算法是:找出根到2个节点的路径,然后从根遍历,当最后一个相同的节点,即为最低公共祖父节点。

思路一:

在本题中,如果我们能从最后 1 个节点(如bst中的根) 向前遍历,则很容易找出第一个公共节点,但是单链表只能从前向后遍历。而给定从前到后,如何得到从后向前,可以想到使用先进后出的栈。

因此我们可以用2个栈存储2个链表的节点,然后从栈顶开始逐个比较,找出最后一个相同的节点,即为所求。

时间复杂度O(n), 空间复杂度O(m+n);

思路二:

如例子中观察,如果能够对链表1能够从2节开始链表24节点同步走,逐个比较对应节点,很容易找到公共节点。又如果存在公共节点,则在公共节点之后的节点数相同,因此2个链表的长度之差,即为没有相遇之前的节点数之差。

如果我们让链表长度更长的先走2个链表的长度之差的步数,然后2个链表一起走,则容易找到公共节点。

时间复杂度O(n), 空间复杂度O(1);

#include <iostream>
using namespace std;
class Node {
public:
    int val;
    Node* next;
    Node(int v, Node* n) : val(v), next(n){};
};
int GetLen(const Node*  list) {
    int len = 0;
    while (list != NULL) {
        len++;
        list = list->next;
    }
    return len;
}
Node* FirstCommonNode(Node* list1, Node* list2) {
    if (list1 == NULL || list2 == NULL)
        return NULL;
    int len1 = GetLen(list1);
    int len2 = GetLen(list2);
    while (len1 > len2) {
        list1 = list1->next;
        len1--;
    }
    while (len2 > len1) {
        list2 = list2->next;
        len2--;
    }
    while (list1 && list2) {
        if (list1 == list2)
            return list1;
        list1 = list1->next;
        list2 = list2->next;
    }
    return NULL;
}

int main() {
    Node* common = new Node(6, new Node(7, NULL));
    Node* list1 = new Node(1, new Node(2, new Node(3, common)));
    Node* list2 = new Node(4, new Node(5, common));
    Node* firtNode = FirstCommonNode(list1, list2);
    if (firtNode)
        cout << firtNode->val << endl;
    else
        cout << "No common node" << endl;

}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-09-29 02:34:01

37 - 两个链表的第一个公共节点的相关文章

剑指offer (37) 两个链表的第一个公共结点

题目:输入两个链表,找出它们的第一个公共结点 如果两个链表有公共结点,那么公共结点一定出现在两个链表的尾部 如果两链表长度不相等,那么达到公共结点的步数就不一致,如何确保 两个链表从头开始遍历,同步达到公共结点? 这是关键所在 如果两链表长度相同,那么就可以同步达到了? 由此,我们就需要 让两个链表长度"相等" 我们假设 两链表长度分别为m和n,且m > n, 那么我们可以在较长链表中 先走 m - n 步,然后 两个链表游标同步走,如果有公共结点,那么就一定同时达到 ListN

找到两个链表的第一个公共节点 37

? ? 引言 ? ? 这个问题一种常想到的方法就是两层循环遍历,外层循环遍历链表A,对A中每个节点,遍历链表B,如果在B中找到,说明这个节点是第一个公共节点,但是这样的方法时间复杂为mn,一般是不允采用的 ? ? 分析问题 ? ? 所以我们需要分析更深层次的问题,找到其中的规律,我们如果动手画一下一般的链表图就能够发现两个链表的第一个公共节点之后的样子一定是如下表示(由此可以发现有时候动手是很重要的) ? ? ? ? 可以发现两个链表在第一个节点重合之后不会再分开了 ? ? 简单多说一句不会分开

剑指offer-第五章优化时间和空间效率(两个链表的第一个公共节点)

思路1:要求的是两个链表的第一个公共节点,首先想到的是用栈来存放两个链表,然后依次从栈中抛出,直到最后一个相同的节点为止.但是要用到两个栈,空间复杂度为O(n): 思路2:从头到尾分别遍历两个链表得到链表的长度风别为,len1和len2,求出两者的差值dif,然后现在长的链表上面走dif步,然后同步走剩下的节点,当就可以找到第一个公共节点了. public ListNode findFirstCommonNode(ListNode pHead1,ListNode pHead2){ if(pHea

经典算法学习——打印两个链表的第一个公共节点

求链表的公共节点是一道很经典的算法题,并不是很难.我们需要知道的是,一旦两个链表有一个公共节点的话,那么这两个链表的形状就是一个"Y"型.也就是说,自公共节点之后的所有节点都是一样的.如下: 其实只要看了这幅图,实现就很简单了.首先我们分别遍历两个链表,分别得出他们的长度L1,L2.然后在查找公共节点时,先在长的那个链表中走|L1-L2|步,然后两个链表同时向后进行同步遍历,每走一步时,就判断后面那个节点是否相同.若相同,则找到该第一个公共节点.完整代码上传至 https://gith

【剑指offer】52、两个链表的第一个公共节点

题目 输入两个链表,找出它们的第一个公共结点. 思路一 因为是反向找,所以会想到用栈.将两个链表都压入两个栈,然后反向弹出,找出第一个公共节点.思路很简单 class Solution { public: ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) { stack<ListNode*> s1, s2; if (pHead1 == nullptr || pHead2 == nullptr) return n

36.两个链表的第一个公共节点。

题目描述: ??输入两个链表,找出它们的第一个公共结点. 思路分析: ??由于链表的指针只能指向一个节点,所以两个链表相交后,后面的部分完全一样.所以我们的解题思路就是先求出两个链表的长度,设置俩个指针分别指向两个链表的头部.指向较长链表的指针先走两个链表长度差步,然后两个指针同时开始走,当两个指针指向同一个节点时,这个节点就是第一个公共节点. 代码: /* public class ListNode { int val; ListNode next = null; ListNode(int v

37.两个链表的第一个公共结点

题目:输入两个链表,找出它们的第一个公共结点,链表结点定义如下: struct  ListNode {          int m_nKey;          ListNode*  m_pNext; }; ListNode* FindFirstComonNode(ListNode* pHead1, ListNode* pHead2) { //得到两个链表的长度 unsigned int nLength1 = GetListLength(pHead1); unsigned int nLengt

两个链表的第一个公共节点

已知有两个链表,他们可能相交于某一点,求出该点. 方法1.对于第一个链表,每访问一个节点,对该节点做标记.访问第二个链表,如果该元素已经访问,则第一个这样的元素就是所求点. 由于两个链表都访问了一遍,因此时间复杂度O(m+n),空间复杂度O(m)或O(n) 方法2.我们定义节点的距离为节点到链表开始所经过的节点数.如果两个链表长度相同,则相交节点其在两个链表上的距离一定相等.对于长度不同的两个链表,我们可以采用对齐的方式,使其向长度短的链表对齐.这样就可以应用上面的思路.具体算法如下: [cpp

判断两个链表是否相交;查找两个链表的第一个公共节点

问题一:(引用编程之美)如果两个链表相交,则尾节点一定是公共的 问题二: 1 int listLength(node* list){ 2 int length=0; 3 while(list!=NULL){ 4 length++; 5 list=list->next; 6 } 7 return length; 8 } 9 // 10 node* firstComNode(node* list1,node* list2){ 11 int n1=listLength(list1); 12 int n