jef*_*ffD 44 algorithm loops linked-list cycle
有没有人知道一个算法来查找链表是否只使用两个变量来遍历列表.假设您有一个链接的对象列表,它与哪种类型的对象无关.我在一个变量中有一个指向链表头部的指针,我只有一个其他变量来遍历列表.
所以我的计划是比较指针值以查看是否有任何指针相同.该列表的大小有限,但可能很大.我可以将两个变量都设置为头部,然后用另一个变量遍历列表,总是检查它是否等于另一个变量,但是,如果我确实打了一个循环,我将永远不会离开它.我认为它与遍历列表和比较指针值的不同速率有关.有什么想法吗?
Bai*_*ose 46
我建议使用Floyd's Cycle-Finding Algorithm
aka The Tortoise and the Hare Algorithm
.它具有O(n)复杂性,我认为它符合您的要求.
示例代码:
function boolean hasLoop(Node startNode){
Node slowNode = Node fastNode1 = Node fastNode2 = startNode;
while (slowNode && fastNode1 = fastNode2.next() && fastNode2 = fastNode1.next()){
if (slowNode == fastNode1 || slowNode == fastNode2) return true;
slowNode = slowNode.next();
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
关于维基百科的更多信息:Floyd的循环查找算法.
绝对.一个解决方案确实可以用两个指针遍历列表,一个以两倍的速率行进.
从"慢"和"快速"指针开始,指向列表中的任何位置.运行遍历循环.如果"快速"指针在任何时候与慢速指针一致,则您有一个循环链表.
int *head = list.GetHead();
if (head != null) {
int *fastPtr = head;
int *slowPtr = head;
bool isCircular = true;
do
{
if (fastPtr->Next == null || fastPtr->Next->Next == null) //List end found
{
isCircular = false;
break;
}
fastPtr = fastPtr->Next->Next;
slowPtr = slowPtr->Next;
} while (fastPtr != slowPtr);
//Do whatever you want with the 'isCircular' flag here
}
Run Code Online (Sandbox Code Playgroud)