Java 重构这个递归方法?

Java 重构这个递归方法?,java,recursion,Java,Recursion,我对递归的概念非常陌生,这实际上是我第一次尝试编写递归方法 我试图实现一个递归函数Max,该函数传递一个数组,并带有一个保存数组大小的变量,以便打印最大的元素 这是可行的,但感觉不太对劲 我也注意到,我似乎比我的同学更喜欢使用静态修饰语 任何人都可以提供一些关于如何改进代码的一般提示和反馈吗 public class RecursiveTry{ static int[] n = new int[] {1,2,4,3,3,32,100}; static int current = 0; stat

我对递归的概念非常陌生,这实际上是我第一次尝试编写递归方法

我试图实现一个递归函数Max,该函数传递一个数组,并带有一个保存数组大小的变量,以便打印最大的元素

这是可行的,但感觉不太对劲

我也注意到,我似乎比我的同学更喜欢使用静态修饰语

任何人都可以提供一些关于如何改进代码的一般提示和反馈吗

public class RecursiveTry{

static int[] n = new int[] {1,2,4,3,3,32,100};
static int current = 0;
static int maxValue = 0;
static int SIZE = n.length;

public static void main(String[] args){
    System.out.println(Max(n, SIZE));
}   

public static int Max(int[] n, int SIZE) {
    if(current <= SIZE - 1){
        if (maxValue <= n[current]) {
            maxValue = n[current];
            current++;
            Max(n, SIZE);                       
        }
        else {
            current++;
            Max(n, SIZE);
        }
    }
    return maxValue;
}
公共类递归尝试{
静态int[]n=新int[]{1,2,4,3,3,32100};
静态电流=0;
静态int maxValue=0;
静态int SIZE=n.length;
公共静态void main(字符串[]args){
系统输出打印项次(最大(n,大小));
}   
公共静态int Max(int[]n,int SIZE){
如果(current一个“max”函数是编写递归函数的错误类型,而您对“current”和“maxValue”使用的是静态值这一事实使得您的函数不是真正的递归函数


为什么不做一些更适合递归算法的事情,比如阶乘呢?

使用静态变量来保持函数外部的状态将是一个困难的来源

伪代码中max()函数的递归实现示例如下:

function Max(data, size) {
    assert(size > 0)
    if (size == 1) {
        return data[0]
    }
    maxtail = Max(data[1..size], size-1)
    if (data[0] > maxtail) {
        return data[0]
    } else {
        return maxtail
    }
}
这里的关键是对Max()的递归调用,在这里传递除第一个元素之外的所有元素,并且传递一个小于大小的元素。一般的想法是,此函数表示“此数据中的最大值要么是第一个元素,要么是数组其余部分中的最大值,以较大者为准”

此实现不需要函数定义之外的静态数据


递归实现的一个特点是所谓的“终止条件”,它阻止递归永远继续(或者直到堆栈溢出)。在上述情况下,
size==1
的测试是终止条件。

首先,让我们处理静态范围问题…您的类正在定义一个对象,但从未实际实例化一个对象。因为main是静态范围的,所以首先要做的是获取一个对象,然后执行它的方法,如下所示:

public class RecursiveTry{

    private int[] n = {1,2,4,3,3,32,100};

    public static void main(String[] args){
        RecursiveTry maxObject = new RecursiveTry();
        System.out.println(maxObject.Max(maxObject.n, 0));
    }

    public int Max(int[] n, int start) {
        if(start == n.length - 1) {
            return n[start];
        } else { 
            int maxRest = Max(n, start + 1);
            if(n[start] > maxRest) {
                return n[start];
            }
            return maxRest;
        }
    }

}
现在我们有一个名为maxObject的RecursiveTry对象,它不需要静态作用域。我不确定使用递归查找最大值是否有效,因为传统循环方法中的迭代次数大致相等,但使用递归时使用的堆栈量更大。但对于这个示例,我会将其减少很多。


递归的一个优点是,在重复测试期间,您的状态通常不需要像在迭代中那样持久化。在这里,我同意使用变量来保持起点,因为传递新的int[]会减少CPU占用它包含除第一项之外的所有项。

您基本上是在编写迭代版本,但在循环中使用尾部递归。此外,通过将这么多变量设置为静态,您基本上是在使用全局变量而不是对象。下面是一个更接近典型递归实现的尝试。当然,在现实生活中,如果您使用的是像Java这样的不优化尾部调用的语言,那么您将使用循环实现“Max”函数

public class RecursiveTry{
  static int[] n;

  public static void main(String[] args){
        RecursiveTry t = new RecursiveTry(new int[] {1,2,4,3,3,32,100});
        System.out.println(t.Max());
  }       

  RecursiveTry(int[] arg) {
    n = arg;
  }

  public int Max() {
    return MaxHelper(0);
  }

  private int MaxHelper(int index) {
    if(index == n.length-1) {
      return n[index];
    } else {
      int maxrest = MaxHelper(index+1);
      int current = n[index];
      if(current > maxrest)
        return current;
      else
        return maxrest;
    }
  }
}
“不是家庭作业”

不管怎么说,第一件事是第一件事

static int[] n = new int[] {1,2,4,3,3,32,100};
static int SIZE = n.length;
与它们共享名称的Max()参数无关。将这些参数移到main并丢失“静态”说明符。当从main()内部调用Max()的第一个实例时,这些说明符仅使用一次。它们的作用域不应扩展到main()之外

Max()的所有调用都没有理由共享一个“当前”索引。“当前”应该是Max()的本地索引。但是,Max()的连续重复调用如何知道要使用“当前”的值?(提示:Max()已经在传递行下其他Max()的一些数据。将“当前”添加到此数据。)

maxValue也是一样,尽管这里的情况有点复杂。您不仅需要将当前“maxValue”传递到下一行,而且当递归完成时,还必须将其一直传递回第一个Max()函数,该函数将返回到main()。您可能需要看一些其他递归示例,并花一些时间来研究这个示例


最后,Max()本身是静态的。但是,一旦您消除了引用外部数据(静态变量)的需要,这并不重要。它只是意味着您可以调用Max()不必实例化对象。

让函数依赖于静态变量不是一个好主意。下面是递归最大函数的可能实现:

int Max(int[] array, int currentPos, int maxValue) {
    // Ouch!
    if (currentPos < 0) {
        raise some error
    }
    // We reached the end of the array, return latest maxValue
    if (currentPos >= array.length) {
        return maxValue;
    }
    // Is current value greater then latest maxValue ?
    int currentValue = array[currentPos];
    if (currentValue > maxValue) {
        // currentValue is a new maxValue
        return Max(array, currentPos + 1, currentValue);
    } else {
        // maxValue is still a max value
        return Max(array, currentPos + 1, maxValue);
    }
}
...

int[] array = new int[] {...};
int currentPos = 0;
int maxValue = array[currentPos] or minimum int value;  
    maxValue = Max(array, currentPos, maxValue);
int-Max(int[]数组,int-currentPos,int-maxValue){
//哎哟!
如果(当前位置<0){
提出一些错误
}
//我们到达了数组的末尾,返回最新的maxValue
if(currentPos>=array.length){
返回最大值;
}
//当前值是否大于最新的最大值?
int currentValue=数组[currentPos];
如果(currentValue>maxValue){
//currentValue是一个新的maxValue
返回最大值(数组,currentPos+1,currentValue);
}否则{
//maxValue仍然是最大值
返回最大值(数组,currentPos+1,maxValue);
}
}
...
int[]数组=新的int[]{…};
int currentPos=0;
int maxValue=数组[currentPos]或最小int值;
maxValue=Max(数组、currentPos、maxValue);

正如其他人所观察到的,不需要递归来实现Max函数,但使用熟悉的算法来试验新概念可能会很有帮助。因此,下面是简化的代码,并给出以下解释:

public class RecursiveTry
{
    public static void main(String[] args)
    {
        System.out.println(Max(new int[] {1,2,4,3,3,32,100}, 0, 0));
    }   

    public static int Max(int[] n, int current, int maxValue) 
    {
        if(current < n.Length)
        {
            if (maxValue <= n[current] || current == 0))
            {
                return Max(n, current+1, n[current]);
            }
            return Max(n, current+1, maxValue);
        }
        return maxValue;
   }
}
公共类递归尝试
{
公共静态void main(字符串[]args)
{
System.out.println(Max(新的int[]{1,2,4,3,3,32100},0,0));
}   
普布利
(define (max l)
    (if (= (length l) 1)
        (first l)
        (local ([define maxRest (max (rest l))])
          (if (> (first l) maxRest)
              (first l)
              maxRest))))
define max of a list as:
    if the list has one element, return that element
    otherwise, the max of the list will be the max between the first element and the max of the rest of the list
public class Recursion {

    public static void main(String[] args) {
        int[] data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
        System.out.println("Max: " + max(0, data));
    }

    public static int max(int i, int[] arr) {
        if(i == arr.length-1) {
            return arr[i];
        }

        int memo = max(i+1, arr);
        if(arr[i] > memo) {
            return arr[i];
        }
        return memo;
    }
}
public class RecursiveTry {
    public static void main(String[] args) {
        int[] x = new int[] {1,2,4,3,3,32,100};
        System.out.println(Max(x, 0));
    }   

    public static int Max(int[] arr, int currPos) {
        if (arr.length == 0) return -1;
        if (currPos == arr.length) return arr[0];
        int len = Max (arr, currPos + 1);
        if (len < arr[currPos]) return arr[currPos];
        return len;
    }
}