以递归方式查找链表的最大值

时间:2017-03-29 22:07:30

标签: java recursion methods linked-list nodes

我需要在名为Node的类中编写一个名为findMax的Java方法,该类有两个实例变量:int value和Node next。该方法不带参数,必须返回链表的最大值。在程序的上下文中,该方法将始终由链表的第一个节点调用(递归调用除外)。当我偶然发现一个有效的解决方案时,我正在努力完成这个方法:

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();
}

此方法正确返回了我测试过的每个链表的最大值。但是,由于我通过尝试随机排列代码找到了这个解决方案,我真的不觉得我理解这里发生了什么。任何人都可以向我解释这是如何工作的?此外,如果有更有效的解决方案,它将如何实施?

1 个答案:

答案 0 :(得分:3)

您可以想象链接列表如下所示:

val1 - &gt; val2 - &gt; val3 - &gt;空

递归的工作原理是,最终,您可以处理传递给函数的输入而无需进一步递归。在您的情况下,如果next指针为null,则可以处理node.findMax()。也就是说,大小为1的链表的最大值只是值(递归的基本情况),任何其他链表的最大值是该节点值的最大值或其余元素的最大值。

ie)对于值为val3的Node n3n3.findMax()只返回值

对于任何其他节点nn.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;
    }
}