大晚上睡不着,脑海里忽然出现关于链表的问题,可能是我晚上思考会比较冷静,不那么浮躁的原因,所以想到一些解决方法。
一、关于链表交叉
两条链表有交叉,最后会走到一起,如下面的丑图:
问题1,如何判断两条链表是否有交叉?
方法1、最简单粗暴的方法当然是遍历第一条链表的的每个节点的时候,完整遍历第二条链表,看是否有节点相同。
伪代码:
while p1
{
while p2
{
if p1==p2
{
return true;
}
p2 = p2->next;
}
p1 = p1->next;
}
return false;
这种方法虽然实现方法简单,也容易理解,但是效率确实可怕的。。。时间复杂度O(n*m)。n和m代表两条链表的长度。
方法2、既然两条链表交叉之后,最后走在了一起。那么有一个条件一定是成立I的。那就是两条链表的最后一个节点肯定是相同的。通过这个方法也是可以确定两条链表交叉了。
伪代码:
while p1->next
{
p1 = p1->next;
}
while p2->next
{
p2 = p2->next;
}
if p1 == p2
{
return true;
}
return false;
这种方法也很容易理解,效率比上一种却好很多,时间复杂度O(n+m).
那么确定了两条链表有交叉之后。。。问题又来了。。
问题2、交叉点在哪里呢????
不难看出,前面一个问题的第一种解决方法,两条链表相同的第一个节点就是我们要找的节点,但是还是那个问题。。时间复杂度,效率问题。。
我仔细想了想,还有一种方法,与上一问的第二种方法有点关系。先看一下下面的图
看这个图,你有什么想法呢??
第一条链表比较长,那么从第一条链表的某个节点开始遍历(上图中第一个链表的第三个节点),同时第二条链表开始遍历,他们的同时走相同的节点数之后会在某个节点相遇(上图中第一条链表的第五个节点)。那么问题又来了。要从第一条链表的那个节点开始遍历呢?其实很简单,通过上图可以看出这个节点应该位于 n-m 处(n第一条链表的长度,m第二条链表的长度)。
伪代码:
len1 = len2 = 0;
p