Java中链表中的循环检测
问题: 给定一个循环链接的llist,实现一个在循环开始时返回节点的算法 我不是在要求回答这个问题 我知道有一些循环检测算法涉及两个指针以不同的速度移动,我已经知道这个问题的一些答案 然而,我想知道的是,当我第一次试图解决这个问题时,我是这样做的:Java中链表中的循环检测,java,loops,linked-list,nodes,Java,Loops,Linked List,Nodes,问题: 给定一个循环链接的llist,实现一个在循环开始时返回节点的算法 我不是在要求回答这个问题 我知道有一些循环检测算法涉及两个指针以不同的速度移动,我已经知道这个问题的一些答案 然而,我想知道的是,当我第一次试图解决这个问题时,我是这样做的: LinkedListNode loopExists(LinkedListNode node) { HashSet hs = new HashSet(); while(node != null) { if(hs.cont
LinkedListNode loopExists(LinkedListNode node) {
HashSet hs = new HashSet();
while(node != null) {
if(hs.contains(node))
return node;
else
hs.add(node);
node = node.next;
}
return null;
}
我很好奇,因为没有像我在上面贴的那样的答案
问题是询问循环开始处的节点
如果我在链表中迭代检查每个节点(不是node.data),如果我再次找到相同的节点,我假设这就是循环开始处的节点
这种方法有什么问题吗?如果我有什么误解,请告诉我。谢谢 是的,当然,我们可以有多种解决方案。而且,若解决方案不可用,那个么这并不意味着那个不可能是解决方案 例如,另一种解决方案可能是,我们可以在每个节点中设置
标志
属性,并在访问时将标记为选中。在这种情况下,如果同一个节点再次重复,那么我们可以检查标志
属性并检测循环
现在,在您的例子中,您正在使用不必要的内存来存储节点对象,这可以通过运行循环来解决,而无需存储节点对象。是的,当然,我们可以有多个解决方案。而且,若解决方案不可用,那个么这并不意味着那个不可能是解决方案
例如,另一种解决方案可能是,我们可以在每个节点中设置标志
属性,并在访问时将标记为选中。在这种情况下,如果同一个节点再次重复,那么我们可以检查标志
属性并检测循环
现在,在您的例子中,您正在使用不必要的内存来存储节点对象,这可以通过运行循环来解决,而无需存储节点对象。这样的问题更多地属于如何定义循环的开始?它可以是循环中的任何节点,除非我误解了这个问题。循环没有“开始”。输入:A->B->C->D->E->C输出:C我指的是循环的开始和结束(重复)这样的问题更多地属于如何定义循环的开始?它可以是循环中的任何节点,除非我误解了这个问题。循环没有“开始”。输入:A->B->C->D->E->C输出:C我指的是循环的开始和结束(重复)我同意拉维关于内存的评论:哈希集将临时占用与列表大小大致成比例的内存。但它是一个非常简单易读的实现,没有任何问题。两个速度不同的指针占用恒定内存(2个指针),但生成的代码几乎不可读(如果您不知道算法)。我强烈反对引入“flag”字段。loopExists()之类的方法不必更改参数LinkedList的任何状态。有人能详细说明我的解决方案使用不必要的内存存储节点对象这一点吗?我是一个新手,在这里我不能完全理解它,但我以前读过关于记忆的书:(@NomaCitzen好的,首先你要创建一个HashSet
的实例,这将占用一些内存。对吗?现在,一旦你开始循环,在每次迭代中,你将存储每个节点的引用,这些引用将持续增长,直到你找到循环为止。@NomaCitzen你需要澄清你的疑问,一旦你得到答案。哟你需要练习接受它。我同意拉维关于内存的评论:哈希集将临时占用内存,大致与列表大小成比例。但它是一个非常简单易读的实现,没有任何问题。两个速度不同的指针占用恒定内存(2个指针),但生成的代码几乎不可读(如果您不知道算法的话)。我强烈反对引入“flag”字段。类似loopExists()的方法不必更改参数LinkedList的任何状态。有人能详细说明我的解决方案使用不必要的内存来存储节点对象这一点吗?我是一个新手,在这里我不能完全理解它,但我以前读过关于内存的内容:(@NomaCitzen好的,首先你要创建一个HashSet
的实例,这将占用一些内存。对吗?现在,一旦你开始循环,在每次迭代中,你将存储每个节点的引用,这些引用将持续增长,直到你找到循环为止。@NomaCitzen你需要澄清你的疑问,一旦你得到答案。哟你需要练习接受它。