赞
踩
题目:现在有两个链表,你能帮我判断两个链表是否有交叉吗?如果能帮我找出来交叉的节点最好。
分析问题:我们首先想到的是暴力解法, n*n的复杂度,遍历一个链表的同时,再遍历另外一个链表,判断另一个链表里是否有节点是当前的节点。但是,我们再想象一下,链表交叉会是什么样的情况? Y型对吧?不可能是X型对吧(之前和很多候选人聊过,他们弄不清楚相交的场景,这说明对链表没有很深的认识),但是大家想一下,如果给出的是同一个链表的两个节点,这也算是相交。但是大家设想一下,如果其中有一个链表是6字型的,就是说该链表里有环,它藏着巨大的陷阱,循环遍历的时候可以会陷入死循环。还有一点,我们不是判断值相等哦,这是引用类型,相交就是两个指正指向同一个节点。好的,那我们总结一下相交的两种情况:
1. Y字形,两个单链表相交
2. 一个或两个链表存在环,避免死循环。这种情况我们都返回空好了。
如何解题呢(不考虑暴力解法哈)?
1. 我们先处理第一种简单的情况,假设两个链表是独立的,而且没有环。这个简单,我们申明两个指针,分别遍历两个链表,获取其长度,再做差,假设是M。让长的链表先走M步,然后同时出发,每个节点做判断。
2. 假设链表中存在环(如何判断,我会在下一遍里具体讲),我们这里先判断是否存在。#1的做法其实就是不存在环的条件下进行的。我们设上两个指针,在同一个链表中,一个走一步一个走两步也就好了,如果相遇了,至于找出环的入口点,其实不是本算法要解决的问题。在本题当中我们先不考虑有环链表相交的问题,我们讲完环再回来讨论这个问题:
那我们一起看代码:
- /// <summary>
- /// 判断两个链表是否相交
- /// </summary>
- /// <param name="first">第一个链表</param>
- /// <param name="second">第二个链表</param>
- /// <returns>相交的节点</returns>
- public static MyLinkNode<T> Cross(MyLinkNode<T> first, MyLinkNode<T> second)
- {
- bool isFirstCycle = first.IsCycle();
- bool isSecondCycle = second.IsCycle();
-
- #region No Cycle
- if (!isFirstCycle && !isSecondCycle)
- {
- var p1 = first;
- int length1 = 0;
-
- while (p1 != null)
- {
- length1++;
- p1 = p1.Next;
- }
-
- var p2 = second;
- var length2 = 0;
-
- while (p2 != null)
- {
- length2++;
- p2 = p2.Next;
- }
-
- p1 = first;
- p2 = second;
-
- if (length2 > length1)
- {
- var gap = length2 - length1;
-
- while (gap-- > 0)
- {
- p2 = p2.Next;
- }
- }
-
- if (length1 > length2)
- {
- var gap = length1 - length2;
-
- while (gap-- > 0)
- {
- p1 = p1.Next;
- }
- }
-
- while (p1 != null && p2 != null)
- {
- if (p1 == p2)
- {
- return p1;
- }
-
- p1 = p1.Next;
- p2 = p2.Next;
- }
- }
- return null;
- #endregion
- }
如何判断环我们等下一遍文章。大家对有环链表相交问题有什么好的想法也欢迎分享(其实这种情况非常复杂,我之后会分享我的想法,初步看下来,若相交可能会有两个节点(两个均为环入口), 还有一种是在入口点之前相交, 还有一种是给定的有可能是同一个链表的两个节点)。
在面试中如果真遇到了这种问题,我们可以自己抛出问题,争取能缩小范围,把能解决的问题解决好,有时候失也是一种得。或许,你会得到面试官的欣赏。
好了,欢迎大家关注我的公众号,还有我的系列视频教程, 数据结构与算法 和 微软经典算法面试题辅导。大家有什么更好的解法,也欢迎讨论哈。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。