[英]Cracking the Coding Interview, 6th edition, 2.8
问题陈述:给定一个循环链表,实现一个在循环开始时返回节点的algoirthm。
答案密钥提供了比我建议的更复杂的解决方案。 我有什么问题?:
public static Node loopDetection(Node n1) {
ArrayList<Node> nodeStorage = new ArrayList<Node>();
while (n1.next != null) {
nodeStorage.add(n1);
if (nodeStorage.contains(n1.next)) {
return n1;
}
else {
n1 = n1.next;
}
}
return null;
}
你的解决方案是O(n^2)
时间( ArrayList
每个contains()
是O(n)
时间)和O(n)
空间(用于存储nodeStorage
),而“更复杂”的解决方案是O(n)
时间和O(1)
空间。
本书为感兴趣的人提供了以下解决方案,即O(n)
时间和O(1)
空间:
如果我们移动两个指针,一个速度为1,另一个速度为2,如果链表有循环,它们将会结束。 为什么? 想想两辆在赛道上行驶的汽车 - 速度越快的汽车总会越过越慢! 这里棘手的部分是找到循环的开始。 想象一下,作为一个类比,两个人在赛道上比赛,一个赛跑的速度是另一个赛车的两倍。 如果他们在同一个地方开始,他们下一次会什么时候见面? 接下来他们将在下一圈开始时见面。 现在,让我们假设Fast Runner在n步圈上有一个k米的起跑线。 他们什么时候下次见面? 他们将在下一圈开始前达到k米。 (为什么?快跑者会做出k + 2(n-k)步,包括它的头部开始,慢跑者会做n-k步。两者都将在循环开始之前的k步。)现在,去回到问题,当Fast Runner(n2)和Slow Runner(n1)在我们的循环链表中移动时,当n1进入时,n2将在循环上有一个开头。 具体来说,它将具有k的头部起点,其中k是循环之前的节点数。 由于n2具有k个节点的头部起始,因此n1和n2将在循环开始之前与k个节点相遇。 因此,我们现在知道以下内容:1。Head是来自LoopStart的k个节点(根据定义)。 2. MeetingPoint for n1和n2是来自LoopStart的k个节点(如上所示)。 因此,如果我们将n1移回Head并在MeetingPoint保持n2,并以相同的速度移动它们,它们将在LoopStart上相遇。
LinkedListNode FindBeginning(LinkedListNode head) {
LinkedListNode n1 = head;
LinkedListNode n2 = head;
// Find meeting point
while (n2.next != null) {
n1 = n1.next;
n2 = n2.next.next;
if (n1 == n2) {
break;
}
}
// Error check - there is no meeting point, and therefore no loop
if (n2.next == null) {
return null;
}
/* Move n1 to Head. Keep n2 at Meeting Point. Each are k steps
/* from the Loop Start. If they move at the same pace, they must
* meet at Loop Start. */
n1 = head;
while (n1 != n2) {
n1 = n1.next;
n2 = n2.next;
}
// Now n2 points to the start of the loop.
return n2;
}
amit给出了解决方案。 问题是你要么知道要么你不知道,但你不能在面试中弄明白。 由于我从来没有需要在链表中找到一个循环,除了通过面试之外,了解它对我来说毫无意义。 所以对于面试官来说,这是一个面试问题,并期待amir的回答(这很好,因为它有线性时间和零额外空间),这是非常愚蠢的。
所以你的解决方案大多没问题,除了你应该使用哈希表,你必须确保哈希表散列对节点而不是节点的引用 。 假设您有一个包含字符串和“下一个”指针的节点,并且哈希函数对字符串进行哈希处理,并且如果字符串相等则将节点比较为相等。 在这种情况下,你会发现第一个节点有一个重复的字符串,而不是循环开始时的节点,除非你小心。
(amir的解决方案在语言中有一个非常类似的问题,其中==比较对象,而不是引用。例如在Swift中,你必须使用===(比较引用)而不是==(比较对象))。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.