我需要在名为Node的类中编写一个名为findMax的Java方法,该类具有两个实例变量:int值和Node next。该方法不带参数,并且必须返回链表的最大值。在程序的上下文中,该方法将始终由链表的第一个Node调用(递归调用除外)。当我偶然找到一个可行的解决方案时,我正在努力完成该方法:
public int findMax(){
int max = value;
if(next == null){
return max;
}
else{
if(max <= next.findMax()){
max = next.value;
}
else return max;
}
return next.findMax();
}
此方法正确返回了我测试过的每个链表的最大值。但是,由于我是通过尝试随机排列代码来找到此解决方案的,所以我真的不觉得自己了解这里发生的事情。谁能向我解释这是如何/为什么?此外,如果有更有效的解决方案,将如何实施?
最佳答案
您可以想象一个链表看起来像这样:
val1-> val2-> val3->空
递归的原理是,最终,无需进一步递归就可以处理传递给函数的输入。在您的情况下,如果next
指针为null
,则可以处理node.findMax()。也就是说,大小为1的链表的最大值只是该值(递归的基本情况),其他链表的最大值是该节点的值的最大值或其余元素的最大值。
即)对于值为val3的Node n3
,n3.findMax()
仅返回值
对于任何其他节点n
,n.findMax()
返回节点值的最大值或n.next.findMax()
开头示例中的显示方式是:
n1.findMax()
= Max(n1.value, n2.findMax())
= Max(val1, Max(n2.value, n3.findMax())
= Max(val1, Max(val2, n3.value)) // Since n3.next == null
= Max(val1, Max(val2, val3))
这只是整个列表中的最大值
编辑:根据上面的讨论,尽管您说的可能可行,但是有一种编写程序的简单方法:
int findMax() {
if (this.next == null) {
return this.value;
} else {
return Math.max(this.value, this.next.findMax());
}
}
编辑2:关于您的代码为什么起作用(以及为什么不好)的细分:
public int findMax(){
// This variable doesn't serve much purpose
int max = value;
if(next == null){
return max;
}
else{
// This if condition simply prevents us from following
// the else block below but the stuff inside does nothing.
if(max <= next.findMax()){
// max is never used again if you are here.
max = next.value;
}
else return max;
}
// We now compute findMax() again, leading to serious inefficiency
return next.findMax();
}
为什么效率低下?因为对节点上的
findMax()
的每次调用都会对下一个节点上的findMax()
进行两次后续调用。这些呼叫中的每一个都会产生另外两个呼叫,等等解决此问题的方法是通过存储
next.findMax()
的结果,如下所示:public int findMax() {
if (next == null) {
return value;
}
else {
int maxOfRest = next.findMax();
if(value <= maxOfRest) {
return maxOfRest;
}
else return value;
}
}