【问题标题】:Finding the largest element in an array using recursion in Java在Java中使用递归查找数组中的最大元素
【发布时间】:2016-11-22 21:30:25
【问题描述】:

这是我目前所拥有的,但我对如何跟踪索引感到困惑。我会更改方法的参数,但不允许。 我只能使用循环来制作另一个数组。这些是限制。

public class RecursiveFinder {

    static int checkedIndex = 0;
    static int largest = 0;


    public static int largestElement(int[] start){
        int length = start.length;

        if(start[length-1] > largest){
            largest = start[length-1];
            int[] newArray = Arrays.copyOf(start, length-1);
            largestElement(newArray);
        }
        else{
            return largest;
        }
    }


    /**
     * @param args
     */
    public static void main(String[] args) {
        int[] array1 = {0,3,3643,25,252,25232,3534,25,25235,2523,2426548,765836,7475,35,547,636,367,364,355,2,5,5,5,535};
        System.out.println(largestElement(array1));
        int[] array2 = {1,2,3,4,5,6,7,8,9};
        System.out.println(largestElement(array2));
    }

}

【问题讨论】:

  • 那么,maximumElement应该返回索引还是最大元素的值?
  • 您可以保留一个计数器值来跟踪您的索引。
  • 原来的问题是什么?您确定需要解决复制问题吗?
  • 您能否发布更多有关递归问题限制的详细信息?以这种方式使用递归每次都进行复制是非常低效的。但是你使用它的方式意味着索引是数组的长度。
  • 您不能更改方法的参数数量。但是,您能否再创建一种方法以在所需的方法中使用?

标签: java arrays recursion


【解决方案1】:

递归方法不需要将最大值保留在里面。

2参数法

开始调用:

largestElement(array, array.length-1)

方法如下:

public static int largestElement(int[] start, int index) {
    if (index>0) {
        return Math.max(start[index], largestElement(start, index-1))
    } else {
        return start[0];
    }
}

第 3 行方法是最难理解的。它返回两个元素之一,即当前索引和剩余元素中要递归检查的大元素。

条件if (index>0)类似于while循环。只要索引保持正数(到达数组中的元素),就会调用该函数。


1个参数方法

这个有点棘手,因为你必须传递比上一次迭代更小的数组。

public static int largestElement(int[] start) {
    if (start.length == 1) {
        return start[0];
    }
    int max = largestElement(Arrays.copyOfRange(start, 1, start.length));
    return start[0] > max ? start[0] : max;
}

我希望你这样做是出于学习目的,实际上在 Java 中没有人需要这样做。

【讨论】:

  • 我不确定您是否阅读了这个问题。 OP 说方法的参数不能改变。
  • 哦,你是对的。我承认我主要检查了包含代码的正文。
  • 谢谢你,尼古拉斯。是的,相信我,我知道在有这些限制的情况下使用递归是多么徒劳。
【解决方案2】:

对上层试试,把main方法留下就对了。

public class dammm {



public static int largestElement(int[] start){
int largest = start[0];

for(int i = 0; i<start.length; i++) {
    if(start[i] > largest){

        largest = start[i];
    }

    }return largest;
}

【讨论】:

  • 我不确定您是否阅读了这个问题。 OP 说必须使用递归和 for 循环才能复制数组。
  • 需要使用递归
【解决方案3】:

如果您的目标是使用递归来实现这一目标,那么这就是您需要的代码。它不是最有效的,也不是解决问题的最佳方法,但它可能是您所需要的。

public static int largestElement(int[] start){
    int length = start.length;

    if (start.lenght == 1){
        return start[0];
    } else {
        int x = largestElement(Arrays.copyOf(start, length-1))
        if (x > start[length-1]){
            return x;
        } else {
            return start[length-1];
        }
    }       
}

假设您有一组数字,您只需将其中一个数字与其余数字进行比较。

例如,给定集合 {1,8,5},我们只需要检查 5 是否大于 {1,8 }。同样,您必须检查 8 是否大于最大的 {1}。在下一次迭代中,当集合有一个值时,您知道该值是集合中的较大值。

所以,你回到上一级,检查返回值(1)是否大于8。结果 (8) 返回到上一级并对照 5 进行检查。结论是8是较大的值

【讨论】:

    【解决方案4】:

    一个参数,不能复制。 棘手的是,我们需要将一个较小的数组传递给同一个方法。所以需要一个全局变量。

        // Number of elements checked so far.
        private static int current = -1;
    
        // returns the largest element.
        // current should be -1 when user calls this method.
        public static int largestElement(int[] array) {
            if (array.length > 0) {
                boolean resetCurrent = false;
    
                if (current == -1) {
                    // Initialization
                    current = 0;
                    resetCurrent = true;
                } else if (current >= array.length - 1) {
                    // Base case
                    return array[array.length - 1];
                }
    
                try {
                    int i = current++;
                    return Math.max(array[i], largestElement(array));
                } finally {
                    if (resetCurrent) {
                        current = -1;
                    }
                }
            }
            throw new IllegalArgumentException("Input array is empty.");
        }
    

    如果你能创建另一个方法,一切都会简单得多。

    private static int recursiveFindLargest(int [] array, int i) {
        if (i > 0) {
            return Math.max(array[i], recursiveFindLargest(array, i-1));
        } else {
            return array[0];
        }
    }
    
    public static int largestElement(int [] array) {
        // For empty array, we cannot return a value to indicate this situation,
        //all integer values are possible for non-empty arrays.
        if (array.length == 0) throw new IllegalArgumentException();
    
        return recursiveFindLargest(array, array.length - 1);
    }
    

    【讨论】:

      【解决方案5】:

      对于这个问题,您确实需要考虑使用基本情况。看看您必须处理的一些简单案例:

      1. 如果数组长度为 1,则返回唯一值
      2. 如果数组长度为 2,则返回两个值中的最大值
      3. 如果数组长度为 3,那么 ?

      从上面我们可以大致了解问题的结构:

      if array.length == 1 then
          return array[0]
      else
          return the maximum of the values
      

      在上面如果我们只有一个元素,它是列表中的最大值。如果我们有两个值,那么我们必须找到这些值的最大值。由此,我们可以使用这样的想法,如果我们有三个值,我们可以找到其中两个的最大值,然后将最大值与第三个值进行比较。将其扩展为伪代码,我们可以得到如下内容:

      if array.length == 1 then
          return array[0]
      else
          new array = array without the first element (e.g. {1, 2, 3} => {2, 3})
          return maximum(array[0], largestElement(new array))
      

      为了更好地解释上述内容,可以将执行想象成一个链(例如 {1, 2, 3})。

      • 数组:{1, 2, 3},最大值(数组 [0] = 1,最大元素(新数组 = {2, 3}))
        • 数组:{2, 3},最大值(数组 [0] = 2,最大元素(新数组 = {3}))
          • 数组:{3},数组[0] = 3 => 长度为 1 所以返回 3

      然后上面的内容会回滚我们得到的“树”结构:

      maximum (1, maximum(2, (return 3)))
      

      一旦你有了最大值,你就可以使用上面的示例原理,通过单独的方法找到索引:

      indexOf(array, maximum)
          if array[0] == maximum then
             return 0
          else if array.length == 1 then
             return -1 
          else
             new array = array without the first element (e.g. {1, 2, 3} => {2, 3})
             result = indexOf(new array, maximum)
             return (result == -1) ? result : result + 1
      

      为了进一步了解这一点,我会阅读 Racket 语言中的this。从本质上讲,它展示了纯粹由pairs 组成的数组的想法,以及如何使用递归对其进行迭代。

      如果您有兴趣,Racket 是理解递归的一个很好的资源。您可以在 Racket 上查看滑铁卢大学tutorial。它可以以易于理解的方式向您简要介绍递归,并通过一些示例引导您更好地理解它。

      【讨论】:

        【解决方案6】:

        您不需要在方法之外保留 largest 变量 - 这通常不是递归的好习惯,它应该返回结果的所有上下文。

        当您考虑递归时,请尝试根据答案显而易见的简单基本情况进行思考,然后对于所有其他情况如何将其分解为更简单的情况。

        所以在伪代码中你的算法应该是这样的:

        func largest(int[] array)
            if array has 1 element
                return that element
            else
                return the larger of the first element and the result of calling largest(remaining elements)
        

        您可以使用Math.max 进行“更大”的计算。

        很遗憾,您无法更改参数,因为如果您可以将索引传递给 start at 或使用列表和子列表,则会更容易。但是您的复制方法应该可以正常工作(假设效率不是问题)。

        上述算法的替代方法是将空数组作为基本情况。这具有处理空数组的优势(通过返回 Integer.MIN_VALUE):

        int largest(int[] array) {
            return array.length == 0 
                ? Integer.MIN_VALUE
                : Math.max(array[0], largest(Arrays.copyOfRange(array, 1, array.length)));
        }
        

        【讨论】:

        • 那么我将如何使用 Math.max。我需要一个辅助方法吗?另外,这个方法如何准确地跟踪索引?
        • 我添加了一个使用 Math.max 的示例。我不确定您对跟踪索引是什么意思。没有必要这样做。
        【解决方案7】:

        这是具有一种方法参数的代码的工作示例

            public int max(int[] list) {
                if (list.length == 2) return Math.max(list[0], list[1]);
                int max = max(Arrays.copyOfRange(list, 1, list.length));
                return list[0] < max ? max : list[0];
            }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-11-26
          • 1970-01-01
          • 2016-07-05
          • 2012-12-25
          • 1970-01-01
          • 2015-11-19
          相关资源
          最近更新 更多