通过递归查找数组中最大的正int

时间:2009-12-31 09:52:40

标签: java recursion puzzle

我决定递归地实现一个非常简单的程序,看看Java如何处理递归*,并且有点简短。这就是我最后写的:

public class largestInIntArray {
  public static void main(String[] args)
  {
    // These three lines just set up an array of ints:
    int[] ints = new int[100];
    java.util.Random r = new java.util.Random();
    for(int i = 0; i < 100; i++) ints[i] = r.nextInt();

    System.out.print("Normal:"+normal(ints,-1)+" Recursive:"+recursive(ints,-1));
  }

  private static int normal(int[] input, int largest) {
    for(int i : input)
      if(i > largest) largest = i;

    return largest;
  }

  private static int recursive(int[] ints, int largest) {
    if(ints.length == 1)
      return ints[0] > largest ? ints[0] : largest;

    int[] newints = new int[ints.length - 1];
    System.arraycopy(ints, 1, newints, 0, ints.length - 1); 

    return recursive(newints, ints[0] > largest ? ints[0] : largest);
  }
}

这样做很好,但因为它有点难看,我想知道是否有更好的方法。如果有人有任何想法/替代/语法糖分享,那将非常感激!

P.S。如果你说“使用Lisp”你什么都不赢(但尊重)。我想知道是否可以在 Java 中看起来很好。

*以及 I 处理递归的程度

11 个答案:

答案 0 :(得分:10)

以下是我如何使递归方法看起来更好:

  private static int recursive(int[] ints, int largest, int start) {
    if (start == ints.length) {
      return largest;
    }
    return recursive(ints, Math.max(ints[start], largest), start + 1);
  }

这避免了昂贵的数组副本,并适用于空输入数组。您可以实现一个额外的重载方法,只有两个参数用于与迭代函数相同的签名:

  private static int recursive(int[] ints, int largest) {
    return recursive(ints, largest, 0);
  }

答案 1 :(得分:7)

2项改进:

  • 没有数组副本(只使用偏移量)
  • 无需提供当前最大值

    private static int recursive(int[] ints, int offset) {
        if (ints.length - 1 == offset) {
            return ints[offset];
        } else {
            return Math.max(ints[offset], recursive(ints, offset + 1));
        }
    }
    

使用recursive(ints, 0)开始递归。

答案 2 :(得分:2)

您可以将当前索引作为参数传递,而不是每次都复制几乎整个数组,或者您可以使用分而治之的方法。

答案 3 :(得分:1)

public static int max(int[] numbers) {
  int size = numbers.length;
  return max(numbers, size-1, numbers[size-1]);
}

public static int max(int[] numbers, int index, int largest) {
  largest = Math.max(largest, numbers[index]);
  return index > 0 ? max(numbers, index-1, largest) : largest;
}

答案 4 :(得分:1)

  

...看看Java处理递归的程度

简单的答案是Java不能很好地处理递归。具体来说,Sun java编译器和Hotspot JVM不实现尾调用递归优化,因此递归密集型算法很容易消耗大量的堆栈空间。

但是,我看过有些文章说IBM的JVM 支持这种优化。我看到一封非Sun公司的电子邮件,他说他将其作为一个实验性Hotspot扩展添加为论文项目。

答案 5 :(得分:1)

这里有一个细微的变化,显示了链接列表对递归的好处,其中“更好”意味着“方法签名中的参数更少”

  private static int recursive(LinkedList<Integer> list) {
    if (list.size() == 1){
      return list.removeFirst();
    }
    return Math.max(list.removeFirst(),recursive(list));
  }

答案 6 :(得分:0)

您的递归代码使用System.arrayCopy,但您的迭代代码不会这样做,因此您的微基准测试不准确。正如其他人所提到的,您可以使用Math.min并使用数组索引而不是类似于队列的方法来清理该代码。

答案 7 :(得分:0)

public class Maximum 
{

    /**
     * Just adapted the iterative approach of finding maximum and formed a recursive function
     */
    public static int max(int[] arr,int n,int m)
    {
        if(m < arr[n])
        {
            m = arr[n];
            return max(arr,n - 1,m);
        }
        return m;
    }
    public static void main(String[] args) 
    {
       int[] arr = {1,2,3,4,5,10,203,2,244,245,1000,55000,2223};
       int max1 =  max(arr,arr.length-1,arr[0]);
       System.out.println("Max: "+ max1);
    }
}

答案 8 :(得分:0)

我实际上有一个预制类,我设置它来查找任何值集的最大整数。您可以将此类放入项目中,只需在任何类中使用它,如下所示:

 System.out.println(figures.getLargest(8,6,12,9,120));

这将返回值“120”并将其放在输出中。如果您有兴趣使用它,那么这是方法源代码:

public class figures {

public static int getLargest(int...f) {
   int[] score = new int[f.length];
    int largest=0;
    for(int x=0;x<f.length;x++) {
        for(int z=0;z<f.length;z++) {
            if(f[x]>=f[z]) {
                score[x]++;
            }else if(f[x]<f[z]) {

            }else {
                continue;
            }
            if(z>=f.length) {
                z=0;
                break;
            }
        }
    }
    for(int fg=0;fg<f.length;fg++) {
        if(score[fg]==f.length) {
            largest = f[fg];
        }
    }
    return largest;
    }
}

答案 9 :(得分:0)

以下是我的Java讲师吴教授在他的一个讲座中给出的示例代码。希望它有所帮助。

import java.util.Random;

public class Recursion
{
static int s = 0;

public static Double max(Double[] d, int n, Double max)
{
if (n==0) { return max;}
else
{

if (d[n] > max)
{
max = d[n];
}

return max(d, n-1, max);

}
}

public static void main(String[] args)
{
Random rn = new Random();
Double[] d = new Double[15];

for (int i=0; i {
d[i] = rn.nextDouble();
System.out.println(d[i]);
}

System.out.print("\nMax: " + max(d, d.length-1, d[0]));
}
}

答案 10 :(得分:0)

这是我的替代

public class recursion
{
  public static int max( int[] n, int index )
  {
    if(index == n.length-1)   // If it's simple, solve it immediately:
      return n[index];        // when there's only one number, return it
    if(max(n, index+1) > n [index]) // is one number bigger than n?
      return max(n, index+1); // return the rest, which contains that bigger number
    return n[index];          // if not, return n which must be the biggest number then
  }

  public static void main(String[] args)
  {
    int[] n = {100, 3, 5, 1, 2, 10, 2, 15, -1, 20, -1203}; // just some numbers for testing
    System.out.println(max(n,0));
  }
}