【问题标题】:Finding Max value in an array using recursion使用递归查找数组中的最大值
【发布时间】:2013-11-04 14:17:22
【问题描述】:

对于我被要求解决的问题之一,我使用 for 循环找到了数组的最大值,因此我尝试使用递归找到它,这就是我想出的:

public static int findMax(int[] a, int head, int last) {

    int max = 0;
    if (head == last) {
        return a[head];
    } else if (a[head] < a[last]) {
        return findMax(a, head + 1, last);
    } else {
        return a[head];
    }
}

所以它工作正常并获得最大值,但我的问题是:对于基本情况返回 a[head] 和头部的值是 > 最后值的情况是否可以?

【问题讨论】:

  • 是的,我做到了,它有效
  • 这不是你的错,但是通过递归找到数组中的最大值是完全愚蠢的。这是对递归技术的滥用。
  • 我基本上知道如何使用for循环获取最大值,所以我想尝试使用递归写出代码
  • 这对于数组{2,42,1} 应该会失败,如果 head=0 且 last=2,则该方法将返回 2 而无需递归。
  • @Ingo 它实际上返回 42 作为最大值。编辑:没关系你是对的!

标签: java recursion


【解决方案1】:

private static int getMax(int [] arr, int idx) {

    if (idx==arr.length-1 ) return arr[idx];

    
    return Math.max(arr[idx], getMax (arr,idx+1 ));
}

【讨论】:

    【解决方案2】:
    static int maximumOFArray(int[] array,int n) {
        
        
        int max=Integer.MIN_VALUE;
        
        if(n==1) return array[0];
        else
            max=maximumOFArray(array, --n);
    
        max= max>array[n] ? max : array[n];
        return max;
            
    }
    

    【讨论】:

    • 这是一个简单的递归解决方案,没有类方法调用............
    • 考虑为您的答案添加解释。另外,提供空数组时它不起作用
    【解决方案3】:

    感谢@Robert Columbia 的建议!

    更新: 下面的函数将从索引 0 开始递归,它会不断添加到这个索引值直到它等于数组的长度,如果它更多我们应该停止并返回0. 一旦我们这样做了,我们需要得到数组中每两个项目的最大值,例如:

    A = [1 , 2 , 3 ];
    
    A[0] ( 1 ) vs A[1] ( 2 ) = 2 
    A[1] ( 2 ) vs A[2] ( 3 ) = 3
    Max(2,3) = 3 ( The answer )  
    
    
    
    
    
    public int GetMax(int [] A, int index)  {
    
         index += 1;
         if (index >= A.Length) return 0;
         return Math.Max(A[index], GetMax(A, index + 1));
    
     }
    

    【讨论】:

    • 虽然这段代码可以回答问题,但最好解释一下如何解决问题并提供代码供参考。纯代码的答案往往效用低下,而且可能令人困惑。
    【解决方案4】:

    优化方案

    public class Test1 {
        public static int findMax(int[] a, int head, int last) {
    
            int max = 0, max1 = 0;
    
            if (head == last) {
                return a[head];
    
            } else if (a[head] < a[last]) {
                max = findMax(a, head + 1, last);
            } else
                max = findMax(a, head, last - 1);
    
            if (max >= max1) {
                max1 = max;
            }
            return max1;
    
    
        }
    
        public static void main(String[] args) {
            int arr[] = {1001, 0, 2, 1002, 2500, 3, 1000, 7, 5, 100};
            int i = findMax(arr, 0, 9);
            System.out.println(i);
        }
    }
    

    【讨论】:

      【解决方案5】:

      这不好! 您的代码不会在数组中找到最大元素,它只会返回值高于它旁边的元素的元素,为了解决这个问题,可以将范围内的最大值元素作为递归的参数传递方法。

          private static int findMax(int[] a, int head, int last,int max) {
          if(last == head) {
              return max;
          }
          else if (a[head] > a[last]) {
                  max = a[head];
                  return findMax(a, head, last - 1, max);
              } else {
                  max = a[last];
                  return findMax(a, head + 1, last, max);
              }
      }
      

      【讨论】:

        【解决方案6】:
        class Test
        {
            int high;
            int arr[];
            int n;
            Test()
            {
                n=5;
                arr = new int[n];
                arr[0] = 10;
                arr[1] = 20;
                arr[2] = 30;
                arr[3] = 40;
                arr[4] = 50;
                high = arr[0];
            }
            public static void main(String[] args)
            {
               Test t = new Test();
               t.findHigh(0);
               t.printHigh();
            }
            public void printHigh()
            {
                System.out.println("highest = "+high);
            }
            public void findHigh(int i)
            {
                if(i > n-1)
                {
                    return;
                }
                if(arr[i] > high)
                {
                    high = arr[i];
                }
                findHigh(i+1);
                return;
            }
        }
        

        【讨论】:

          【解决方案7】:

          我遇到了这个帖子,它对我帮助很大。附件是我在递归和分治两种情况下的完整代码。 分而治之的运行时间略好于递归。

          //use divide and conquer.
          public int findMaxDivideConquer(int[] arr){
              return findMaxDivideConquerHelper(arr, 0, arr.length-1);
          }
          private int findMaxDivideConquerHelper(int[] arr, int start, int end){
              //base case
              if(end - start  <=  1) return Math.max(arr[start], arr[end]);
              //divide
              int mid = start + ( end - start )/2;
              int leftMax =findMaxDivideConquerHelper(arr, start, mid);
              int rightMax =findMaxDivideConquerHelper(arr, mid+1, end);
              //conquer
              return Math.max( leftMax, rightMax );
          }
          
          // use recursion. return the max of the current and recursive call
          public int findMaxRec(int[] arr){
              return findMaxRec(arr, 0);
          }
          private int findMaxRec(int[] arr, int i){
              if (i == arr.length) {
                  return Integer.MIN_VALUE;
              }
              return Math.max(arr[i], findMaxRec(arr, i+1));
          }
          

          【讨论】:

            【解决方案8】:

            我知道它是一个旧线程,但也许这会有所帮助!

            public static int max(int[] a, int n) {
                    if(n < 0) {
                        return Integer.MIN_VALUE;
                    }
                    return Math.max(a[n-1], max(a, n - 2));
            
                }
            

            【讨论】:

              【解决方案9】:

              您只需一个计数器即可轻松完成,只需这次要比较的值的索引:

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

              这更好地显示了正在发生的事情,并使用默认的“递归”布局,例如有一个共同的基本步骤。初始呼叫是通过findMax(a, a.length-1)

              【讨论】:

              • if(index) 无法编译 ;)
              • 实际上,我用 2 个计数器计算出来以跟踪索引..就像头计数器将是向数组末尾移动的计数器。在您的回答中,我不明白您为什么使用 Math.max。
              • @ThomasJungblut 谢谢。幸运的是,我通常不编写 Java 程序 :)
              • Math.max 基本上完成了您的 if (a[head] &lt; a[last]) 所做的工作。这基本上是分而治之,您只处理当前索引和其余索引的结果(递归调用)并将它们合并在一起以获得所需的答案。在这种情况下,您想要它们中的最大值,因此您与 Math.max 合并。
              • 为什么要检查索引是否大于0?可以先添加基本情况
              【解决方案10】:

              这个呢?

              public static int maxElement(int[] a, int index, int max) {
                  int largest = max;
                  while (index < a.length-1) {
                      //If current is the first element then override largest
                      if (index == 0) {
                          largest = a[0];
                      }
                      if (largest < a[index+1]) {
                          largest = a[index+1];
                          System.out.println("New Largest : " + largest); //Just to track the change in largest value
                      }
                      maxElement(a,index+1,largest);
                  }
                  return largest;
              }
              

              【讨论】:

                【解决方案11】:

                你可以递归地做如下。

                循环关系是这样的。

                   f(a,n)   = a[n]   if n == size
                            = f(a,n+1) if n != size
                

                实现如下。

                   private static int getMaxRecursive(int[] arr,int pos) {
                         if(pos == (arr.length-1)) {
                                return arr[pos];
                         } else {           
                                return Math.max(arr[pos], getMaxRecursive(arr, pos+1));
                         }
                   }
                

                调用看起来像这样

                      int maxElement = getMaxRecursive(arr,0);
                

                【讨论】:

                  【解决方案12】:
                  int maximum = getMaxValue ( arr[arr.length - 1 ], arr, arr.length - 1 );
                  
                  public static int getMaxValue ( int max, int arr[], int index )
                  {
                      if ( index < 0 )
                          return max;
                      if ( max < arr[index] )
                          max = arr[index];
                      return getMaxValue ( max, arr, index - 1 ); 
                  }
                  

                  我觉得使用跟踪器来获取当前最大值会很好。

                  【讨论】:

                  • 乍一看,这只适用于长度 >= 2 的数组。
                  • 为什么这个提案中有一个length-2?
                  【解决方案13】:

                  我会通过在每次递归调用时将数组分成一半来解决这个问题。

                   findMax(int[] data, int a, int b)
                  

                  其中 a 和 b 是数组索引。

                  停止条件为b - a &lt;= 1时,则为邻居,最大值为max(a,b);

                  初始调用:

                   findMax(int[] data, int 0, data.length -1);
                  

                  这将最大递归深度从 N 减少到 log2(N)。
                  但搜索工作仍然保持 O(N)。

                  这会导致

                  int findMax(int[] data, int a, int b) {
                     if (b - a <= 1) {
                       return Math.max(data[a], data[b]);
                     } else {
                       int mid = (a+b) /2; // this can overflow for values near Integer.Max: can be solved by a + (b-a) / 2; 
                       int leftMax =  findMax(a, mid);
                       int rightMax = findMax(mid +1, b);
                       return Math.max(leftMax, rightMax);
                     }
                  }
                  

                  【讨论】:

                  • 唯一的优化是你减少了堆栈开销,它仍然是相同的 (O(n)) 复杂度。
                  • 确实,@DerFlatulator。因为这里访问了“树”的两侧,所以访问了所有n 元素,对于O(n)。它类似于二分搜索具有误导性,因为对于二分搜索,只访问树的一侧,以达到O(log n) 步骤中的最深元素,以获得平衡树。
                  • 是的,这是唯一的优化,但它增加了可能的数组大小;但这仍然是一个愚蠢的问题;他们应该学习递归二分搜索。
                  • @Joost 已更新以合并您的 cmets。
                  • 无论如何,用递归搜索常规数组并没有什么意义。因此,当您可以切换到迭代方法时尝试对其进行优化似乎是徒劳的。
                  【解决方案14】:

                  实际上比这简单得多。基本情况是如果您已经到达数组的末尾(下面的三元控制块的“else”部分)。否则返回当前和递归调用的最大值。

                  public static int findMax(int[] a) {
                      return findMax(a, 0);
                  }
                  private static int findMax(int[] a, int i) {
                      return i < a.length
                             ? Math.max(a[i], findMax(a, i + 1))
                             : Integer.MIN_VALUE;
                  }
                  

                  在每个元素处,您返回当前元素中较大的一个,以及所有具有较大索引的元素。 Integer.MIN_VALUE 只会在空数组上返回。这在线性时间内运行。

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 2016-05-07
                    • 2012-10-18
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2015-05-03
                    相关资源
                    最近更新 更多