Java 在递归函数中初始化变量
我正在做一个递归函数,它必须没有参数才能得到链表的长度Java 在递归函数中初始化变量,java,variables,recursion,linked-list,initialization,Java,Variables,Recursion,Linked List,Initialization,我正在做一个递归函数,它必须没有参数才能得到链表的长度 public int lengthHelper() { if (first == null) { return 0; } else { first = first.next; return 1 + length(); } } 问题是,通过使用first=first.next,我将首先破坏,首先是我的标题。所以我想先在函数中复制(而不是我丑陋的包装器脚本),但递归会让这
public int lengthHelper() {
if (first == null) {
return 0;
} else {
first = first.next;
return 1 + length();
}
}
问题是,通过使用first=first.next,我将首先破坏,首先是我的标题。所以我想先在函数中复制(而不是我丑陋的包装器脚本),但递归会让这变得很麻烦。你知道怎么做吗
顺便说一句,这是我想删除的包装:
public int length() {
Node temp = copy(first);
int output = this.lengthHelper();
first = copy(temp);
return output;
}
我之所以有这些限制,是因为这是一个基于任务的个人挑战。递归+包装器已经足够了,但从那以后我一直在思考是否有可能以更干净的方式解决它。没有干净的方式来解决这个问题。我建议这样做:
public int length() {
return computeLength(this.first);
}
private int computeLength(Node node) {
if (node == null) return 0;
return 1 + computeLength(node.next);
}
做这件事没有干净的方法。我建议这样做:
public int length() {
return computeLength(this.first);
}
private int computeLength(Node node) {
if (node == null) return 0;
return 1 + computeLength(node.next);
}
这是一个相当人为的要求。:)但是,如何先将
存储在本地堆栈帧中,然后在返回之前恢复它呢
这听起来像是一个家庭作业问题,所以也许我不应该说出完整的答案。但基本上是这样的:
- 创建一个局部变量来存储
first的当前值
- 首先更新
,
,从而打破列表(如您所指出的)
- 向下递归,并将该递归的结果保存在第二个局部变量中
- 使用第一个局部变量还原第一个
要获得额外的积分,请尝试这样做,如果您在过程中碰巧遇到异常(例如堆栈溢出),则不会打破列表。提示:
try finally
这是一个非常人为的要求。:)但是,如何先将存储在本地堆栈帧中,然后在返回之前恢复它呢
这听起来像是一个家庭作业问题,所以也许我不应该说出完整的答案。但基本上是这样的:
- 创建一个局部变量来存储
first的当前值
- 首先更新
,
,从而打破列表(如您所指出的)
- 向下递归,并将该递归的结果保存在第二个局部变量中
- 使用第一个局部变量还原第一个
要获得额外的积分,请尝试这样做,如果您在过程中碰巧遇到异常(例如堆栈溢出),则不会打破列表。提示:
try finally
如果我正确理解首先
是递归数据结构节点
,并且在非递归容器类列表
(例如)中,您需要定义递归方法(不带参数)
然后,解决方案是在List
中使用一个方法,该方法生成一个新的尾部/剩余部分列表,而不使用first
。下面我假设一个构造函数有一个节点
class Node { }
public class List {
Node first;
public int length() {
if (first == null) {
return 0;
} else {
List tail = new List(first.next);
return 1 + tail.length();
}
}
如果我正确理解了
首先
是递归数据结构节点
,并且在非递归容器类列表
(例如)中,您需要定义一个递归方法(不带参数)
然后,解决方案是在List
中使用一个方法,该方法生成一个新的尾部/剩余部分列表,而不使用first
。下面我假设一个构造函数有一个节点
class Node { }
public class List {
Node first;
public int length() {
if (first == null) {
return 0;
} else {
List tail = new List(first.next);
return 1 + tail.length();
}
}
递归方法是否必须是无参数的?我是否正确地假设
first
是列表的开头,并且是一个私有实例变量?是和是。不允许使用参数,第一个是我的headIslength
可能应该是list类的一个方法?递归方法是否必须是无参数的?我是否正确地假设first
是列表的头并且是一个私有实例变量?是和是。不允许使用参数,首先是我的headIslength
可能应该是list类的一个方法?这仍然是相同的问题,但比我做的要干净得多。可能会满足于它,除非有人有一个尤里卡时刻。我认为没有某种形式的参数是不可能的。通过使用类变量存储递归状态(在您的示例中是“第一个”对象),您只需冒着在其他地方破坏它的风险。我可以问你为什么要这样做吗?这仍然是一个问题,但它比我做的要干净得多。可能会满足于它,除非有人有一个尤里卡时刻。我认为没有某种形式的参数是不可能的。通过使用类变量存储递归状态(在您的示例中是“第一个”对象),您只需冒着在其他地方破坏它的风险。我可以问一下你为什么要这样做吗?太棒了,我看起来就是这样。老实说,这是一个家庭作业问题。不过,我的教授对难看的包装解决方案很满意。在那之后,我无法停止思考是否有办法将其移除。个人挑战,如果你愿意的话。太棒了,正是我所期待的。老实说,这是一个家庭作业问题。不过,我的教授对难看的包装解决方案很满意。在那之后,我无法停止思考是否有办法将其移除。这实际上与我下面的答案非常相似,主要的两个区别是:(1)不破坏列表,然后修复列表;(2)临时变量在我的堆栈上,在这个解决方案中位于堆中(newlist
)。它们的相似之处在于,在这两种情况下,您都在创建一个尾部列表(在我的示例中,通过将this
修改为它自己的尾部),获取它的长度,然后丢弃它(在我的示例中,通过还原“this”,让list tail
超出范围)。@yshavit是的,我看到您也喜欢算法和数据结构+1是的。:)我比我更喜欢你的解决方案,尽管它会搅动更多的对象。它的代码更少,线程安全,在出现错误时不会有破坏列表的风险,并且保持每个列表不变。最后一部分实际上让事情变得更糟