判断两链表是否有交点

 我来答
就烦条0o
2018-02-21 · 知道合伙人软件行家
就烦条0o
知道合伙人软件行家
采纳数:33315 获赞数:46492
从事多年系统运维,喜欢编写各种小程序和脚本。

向TA提问 私信TA
展开全部

1、直接法

采用暴力的方法,遍历两个链表,判断第一个链表的每个结点是否在第二个链表中,时间复杂度为O(len1*len2),耗时很大。

2、hash计数法

如  果  两个链表相交,则两个链表就会有共同的结点;而结点地址又是结点唯一标识。因而判断两个链表中是否存在地址一致的节点,就可以知道是否相交了。可以对第一   个链表的节点地址进行hash排序,建立hash表,然后针对第二个链表的每个节点的地址查询hash表,如果它在hash表中出现,则说明两个链表有共   同的结点。这个方法的时间复杂度为:O(max(len1+len2);但同时还得增加O(len1)的存储空间存储哈希表。这样减少了时间复杂度,增加  了存储空间。

以链表节点地址为值,遍历第一个链表,使用Hash保存所有节点地址值,结束条件为到最后一个节点(无环)或Hash中该地址值已经存在(有环)。

再遍历第二个链表,判断节点地址值是否已经存在于上面创建的Hash表中。

这个方面可以解决题目中的所有情况,时间复杂度为O(m+n),m和n分别是两个链表中节点数量。由于节点地址指针就是一个整型,假设链表都是在堆中动态创建的,可以使用堆的起始地址作为偏移量,以地址减去这个偏移量作为Hash函数

3、第三种思路是比较奇特的,在编程之美上看到的。先遍历第一个链表到他的尾部,然后将尾部的next指针指向第二个链表(尾部指针的next本来指向的是null)。这样两个链表就合成了一个链表,判断原来的两个链表是否相交也就转变成了判断新的链表是否有环的问题了:即判断单链表是否有环?

这样进行转换后就可以从链表头部进行判断了,其实并不用。通过简单的了解我们就很容易知道,如果新链表是有环的,那么原来第二个链表的头部一定在环上。因此我们就可以从第二个链表的头部进行遍历的,从而减少了时间复杂度(减少的时间复杂度是第一个链表的长度)。

下图是一个简单的演示:

这种方法可以判断两个链表是否相交,但不太容易找出他们的交点。

4、仔细研究两个链表,如果他们相交的话,那么他们最后的一个节点一定是相同的,否则是不相交的。因此判断两个链表是否相交就很简单了,分别遍历到两个链表的尾部,然后判断他们是否相同,如果相同,则相交;否则不相交。示意图如下:

判断出两个链表相交后就是判断他们的交点了。假设第一个链表长度为len1,第二个问len2,然后找出长度较长的,让长度较长的链表指针向后移动|len1 - len2| (len1-len2的绝对值),然后在开始遍历两个链表,判断节点是否相同即可。

下面给出一个简单的实现:

/************************************************************************
两个不含环的单链表的相交
相交指的是结点的地址相同,而不是结点的值相同
************************************************************************/

typedef struct node_t  
{  
int data;//data  
struct node_t *next; //next  
}node;  
   
node* find_node(node *head1, node *head2)  
{  
if(NULL == head1 || NULL == head2)  
{  
return NULL;//如果有为空的链表,肯定是不相交的  
}  
node *p1, *p2;  
p1 = head1;  
p2 = head2;  
int len1 = 0;  
int len2 =0;  
int diff = 0;  
while(NULL != p1->next)  
{  
p1 = p1->next;  
len1++;  
}  
while(NULL != p2->next)  
{  
p2 = p2->next;  
len2++;  
}  
if(p1 != p2) //如果最后一个节点不相同,返回NULL  
{  
return NULL;  
}  
diff = abs(len1 - len2);  
if(len1 > len2)  
{  
p1 = head1;  
p2 = head2;  
}  
else  
{  
p1 = head2;  
p2 = head1;  
}  
for(int i=0; i<diff; i++)  
{  
p1 = p1->next;  
}  
while(p1 != p2)  
{  
p1 = p1->next;  
p2 = p2->next;  
}  
return p1;  
}
    腾讯电脑管家
    2018-02-21 · 百度知道官方认证企业
    腾讯电脑管家
    腾讯电脑管家是腾讯公司推出的免费安全管理软件,能有效预防和解决计算机上常见的安全风险,并帮助用户解决各种电脑“疑难杂症”、优化系统和网络环境,是中国综合能力最强、最稳定的安全软件。
    向TA提问
    展开全部
    fnServerData": function ( sSource, aoData, fnCallback ) {
    /* Add some extra data to the sender */
    aoData.push( { "name": "more_data", "value": "my_value" } );
    $.getJSON( sSource, aoData, function (json) {
    /* Do whatever additional processing you want on the callback, then tell DataTables */
    fnCallback(json)
    } );
    }
    已赞过 已踩过<
    你对这个回答的评价是?
    评论 收起
    推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

    为你推荐:

    下载百度知道APP,抢鲜体验
    使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
    扫描二维码下载
    ×

    类别

    我们会通过消息、邮箱等方式尽快将举报结果通知您。

    说明

    0/200

    提交
    取消

    辅 助

    模 式