判断两个链表是否相交

1 假设两个链表都没有环

解题思路

a. 直接循环判断第一个链表的每个节点是否在第二个链表中。但,这种方法的时间复杂度为O(Length(h1) * Length(h2))。显然,我们得找到一种更为有效的方法,至少不能是O(N^2)的复杂度。

b. 针对第一个链表直接构造hash表,然后查询hash表,判断第二个链表的每个节点是否在hash表出现,如果所有的第二个链表的节点都能在hash表中找到,即说明第二个链表与第一个链表有相同的节点。时间复杂度为为线性:O(Length(h1) + Length(h2)),同时为了存储第一个链表的所有节点,空间复杂度为O(Length(h1))。是否还有更好的方法呢,既能够以线性时间复杂度解决问题,又能减少存储空间?

c.转换为环的问题。把第二个链表接在第一个链表后面,如果得到的链表有环,则说明两个链表相交。如何判断有环的问题上面已经讨论过了,但这里有更简单的方法。因为如果有环,则第二个链表的表头一定也在环上,即第二个链表会构成一个循环链表,我们只需要遍历第二个链表,看是否会回到起始点就可以判断出来。这个方法的时间复杂度是线性的,空间是常数。

d.进一步考虑“如果两个没有环的链表相交于某一节点,那么在这个节点之后的所有节点都是两个链表共有的”这个特点,我们可以知道,如果它们相交,则最后一个节点一定是共有的。而我们很容易能得到链表的最后一个节点,所以这成了我们简化解法的一个主要突破口。那么,我们只要判断两个链表的尾指针是否相等。相等,则链表相交;否则,链表不相交。

所以,先遍历第一个链表,记住最后一个节点。然后遍历第二个链表,到最后一个节点时和第一个链表的最后一个节点做比较,如果相同,则相交,否则,不相交。这样我们就得到了一个时间复杂度,它为O((Length(h1) + Length(h2)),而且只用了一个额外的指针来存储最后一个节点。这个方法时间复杂度为线性O(N),空间复杂度为O(1),显然比解法三更胜一筹

2 假设两个链表都有环,情况只有2种:相交于”环上”或相交于”不是环的部分”。因此环一定是在公共部分上的。假如知道其中一个链表上环的任意一个节点,则只需要判断是否在另一个链表上就行了。这里有个疑问?一般意义上,链表有环并不存在这种形式:1->2->3->2->4?

//判断带环不带环时链表是否相交
//2.如果都不带环,就判断尾节点是否相等
//3.如果都带环,判断一链表上俩指针相遇的那个节点,在不在另一条链表上。
bool detect(Node * head1, Node * head2)
{
    Node * circleNode1;
    Node * circleNode2;
    Node * lastNode1;
    Node * lastNode2;  

    bool isCircle1 = isCircle(head1,circleNode1, lastNode1);
    bool isCircle2 = isCircle(head2,circleNode2, lastNode2);  

    //一个有环,一个无环
    if(isCircle1 != isCircle2)
        return false;
    //两个都无环,判断最后一个节点是否相等
    else if(!isCircle1 && !isCircle2)
    {
        return lastNode1 == lastNode2;
    }
    //两个都有环,判断环里的节点是否能到达另一个链表环里的节点
    else
    {
        Node * temp = circleNode1->next;  //updated,多谢苍狼 and hyy。
        while(temp != circleNode1)
        {
            if(temp == circleNode2)
                return true;
            temp = temp->next;
        }
        return false;
    }  

    return false;
}  

3   求相交的第一个元素

对于1中相交,只要知道两个链表长度L1和L2,那么让长的那个先走abs(L1-L2),然后一起走,相同的那个节点就是第一个元素

//求两链表相交的第一个公共节点
Node* findIntersectNode(Node *h1,Node *h2)
{
    int len1 = listLength(h1);          //求链表长度
    int len2 = listLength(h2);
    //对齐两个链表
    if(len1 > len2)
    {
        for(int i=0;i<len1-len2;i++)
            h1=h1->next;
    }
    else
    {
        for(int i=0;i<len2-len1;i++)
            h2=h2->next;
    }

    while(h1 != NULL)
    {
        if(h1 == h2)
            return h1;
        h1 = h1->next;
        h2 = h2->next;
    }
    return NULL;
}

http://wuchong.me/blog/2014/03/25/interview-link-questions/

http://blog.csdn.net/v_july_v/article/details/6447013

时间: 2024-11-03 05:32:42

判断两个链表是否相交的相关文章

编程之美---判断两个链表是否相交

首先,判断一个链表是否有环? 对于这个问题:可以用两个指针,刚开始都指向头节点,然后一个指针每次向后移一步,另一个指针每次向后移两步,如果最后移两步的指针为空时,说明无环,如果最后两个指针相等,说明有环.如果把第一指针看成静止,则相当于第二个每次走一步,所以在那个环上时,是一定能相遇的. 如何找到这个链表环的入口? 当这两个指针相遇后,把第一个指针移向头,两个指针每次都只移一步,再次相等时,就是环的入口.证明:设环上相遇位置为距离环入口处P,入口处前有M个节点,,环肾功能有N个节点,从入口处开始

数据结构和算法设计专题之---判断两个链表是否相交并找出交点

题目: 一个比较经典的问题,判断两个链表是否相交,如果相交找出他们的交点. 首先来看一下如何判断两个链表是否存在相交的节点: 思路: 1.碰到这个问题,第一印象是采用hash来判断,将两个链表的节点进行hash,然后判断出节点,这种想法当然是可以的. 2.当然采用暴力的方法也是可以的,遍历两个链表,在遍历的过程中进行比较,看节点是否相同. 3.第三种思路是比较奇特的,在编程之美上看到的.先遍历第一个链表到他的尾部,然后将尾部的next指针指向第二个链表(尾部指针的next本来指向的是null).

【IT公司100题-7】-判断两个链表是否相交

问题:有一个单链表,其中可能有一个环,也就是某个节点的next指向的是链表中在它之前的节点,这样在链表的尾部形成一环.1.如何判断一个链表是不是这类链表? 问题扩展:1.如果链表可能有环呢?2.如果需要求出两个链表相交的第一个节点呢? 分析: 在无环的情况下,如果两个链表有结点相同,那么它们下一结点也相同,如此可推出尾结点也相同. 那么只要判断两链表的尾结点是否相同.(O(len1+len2)) 1 struct Node { 2 int data; 3 int Node *next; 4 };

链表相交问题:判断两个链表是否相交,若相交求交点

默认为不带环链表,若带环则延伸为判断链表是否带环,若带环,求入口点 看看两个链表相交到底是怎么回事吧,有这样的的几个事实:(假设链表中不存在环) (1)一旦两个链表相交,那么两个链表中的节点一定有相同地址. (2)一旦两个链表相交,那么两个链表从相交节点开始到尾节点一定都是相同的节点. #include<iostream> #include<assert.h> using namespace std; template<class T> struct LinkNode

数字之魅:判断两个链表是否相交

题目:给出两个链表的头指针,比如head1和head2,判断这两个链表是否相交.这里为了化简,我们假设两个链表均不带环. 方案一:蛮力法.一般我们都能想到的,就是从head1开始,逐个与head2中的每个结点的地址比较,看是否相等,如果不等,则head1移动到下一个结点,继续和head2中的每一个结点的地址比较:如果找到相等,则这两个链表相交:直到head1==NULL,则不相交.注意为了避免存在相同的元素,我们采取比较地址的方法,而不是比较元素,在判断链表里是否有环的时候,也是采用比较地址的方

判断两条链表是否相交(公共部分)并找出相交处

Problem: 两个单链表相交的一系列问题 [题目] 在本题中,单链表可能有环,也可能无环.给定两个 单链表的头节点 head1和head2,这两个链表可能相交,也可能 不相交.请实现一个函数, 如果两个链表相交,请返回相交的 第一个节点:如果不相交,返回null 即可. 要求: 如果链表1 的长度为N,链表2的长度为M,时间复杂度请达到 O(N + M),额外 空间复杂度请达到O(1) Solution: 对于判断单链表是否有环,则使用快慢指针即可知道,两指针相交,则有环 对于判断双链表是否

判断两个链表是否相交(带环)

解决方案: 1.找出链表1的环入口节点a1,链表2的环入口节点a2; 2.如果a1=a2; 说明两个链表可能在入环之前或者入环第一个节点相交:将a1,a2作为两个链表的最后一个节点,转化为不带环的链表相交:其实在这种情况下已经说明两个链表已经相交了. 3.如果a1!=a2;以a1为基准节点进行while循环,如果在循环中找到跟a2相同的节点,说明两个链表相交:如果没找到,说明不相交. #如果1个链表不带环,1个链表带环:则两个链表必不相交:

编程之美3.6—判断两个链表是否相交

解法一: 判断第一个链表的每个节点是否在第二个链表中,O(M*N): 解法二: 对第一个链表的节点地址hash排序,建立hash表,然后对第二个链表的每个节点的地址查询hash表,如出现,相交 时间复杂度O(M+N),空间复杂度O(M). 解法三: 把第二个链表接在第一个链表后面,得到的链表有环,相交,否则,不相交.' 第二个链表的表头一定在环上,只需从第二个链表开始遍历 时间复杂度O(N),常数空间 解法四: 如果两个没有环的链表相交于某一节点,那么在这个节点之后的所有节点都是两个链表共有的.

判断两个链表是否相交(不带环)

1---2---3 ---4---5---6---7 11---12--- 链表1:1---2---3---4---5---6---7 链表2:11---12---4---5---6---7 解决方案: 1.直接将链表1中的节点与链表2中的节点进行比较:如果存在相同的则相交.缺点:效率慢. 2.将链表1建立hash表:用链表2中的节点在hash表中进行查询:缺点:增加了内存消耗. 3.将链表1的尾节点指针指向链表2的头节点:转而进行链表是否有环判断:如果有环,则相交: 由于链表2的头节点必然在环