【问题标题】:Recursive Range Output from Max and Min最大值和最小值的递归范围输出
【发布时间】:2020-08-27 09:13:09
【问题描述】:

您好,我对 java 编码(初级)非常陌生,我正在学习如何使用递归,但我正在做一些练习,我使用最小值和最大值来获取范围。

我希望输出类似于 min 为 2 且 max 为 10 它打印 2 3 4 5 6 7 8 9 10 作为输出。它也在 min 和 max 之间打印出来,但我不知道我实际上是如何获得输出的。

代码如下:

//package methods;
public class MethodsRecursiveRange {

     public static void main(String[] args) {

          int count = 0;
          System.out.println( Range(count));                                                         

     }

     public static int Range (int count) {

          int min = 2;
          int max = 10;

          for ( int i = 0; i < max ; i++) {

               System.out.println(Range(count));
               Range(count);
          }
          return (0); 
     }
}

递归函数出现stack overflow 错误。

【问题讨论】:

  • 您需要为递归函数设置一个停止条件。否则递归函数会一直运行下去。
  • 我该怎么做?我如何让它停止?我也应该添加哪一行?
  • 也许可以尝试一些有用的递归问题
  • 我认为如果你先下定决心递归方法应该是什么样子会更好。您可以在Recursion In Java 下找到一篇易于阅读的文章
  • @NISHANAJIHAH 您能否接受以下其中一项或解释为什么这些答案不起作用?

标签: java range max min


【解决方案1】:

在此处尝试类似下面的操作,您可以在当前 >= 最大值处停止。 请找到内联 cmets 的代码。

public class MethodsRecursiveRange {

    public static void main(String[] args) {
        Range(2,10); // Start
    }

    public static int Range (int curr, int max) {
        System.out.println(curr);   // Print the current value
        if(max<=curr) {             // Check if the Current value is greater or equal to Maximum limit
            return 0;               // Stop the recursion with 0 as return value
        } 
        return Range(++curr,max);   // Continue recursion with keeping max same, increment current value and invoke Range 

    }
}

【讨论】:

    【解决方案2】:

    您使用for 循环破坏了递归的目的。

    关于递归函数/方法,最重要的三件事:

    1. 终止条件。
    2. 递归调用方法/函数的值。
    3. 处理参数的位置(递归调用之前/之后)。

    按如下方式进行:

    public class Main {
        public static void main(String[] args) {
            range(2, 10);
        }
    
        public static void range(int min, int max) {
            if (max <= min - 1) {// The terminating condition
                return;
            }
            range(min, max - 1);// The recursive call
            System.out.print(max + " ");// Processing the parameter(s)
        }
    }
    

    输出:

    2 3 4 5 6 7 8 9 10 
    

    附带说明,您应该始终关注Java naming conventions,例如方法的名称应该是range 而不是Range

    【讨论】:

    • 为什么有些代码使用 +1 和一些 -1 而在 System.out.print(max + " "); 使用 (max + " ") 我不明白这个 + 事情
    • @NISHANAJIHAH - 对于递归函数,您需要一个基本条件,之后不会有递归调用。因此,要满足基本条件,您需要不断从 min 递增到 max so +1,或者需要不断从 max 递减到 min so -1
    • @Arvind 如果有人调用 range(10, 2);错误地,您的代码将永远不会满足基本条件并会抛出 stackoverflow
    • @Swetank 你所说的基本条件是什么意思?
    • @NISHANAJIHAH 基本条件也称为终止条件,这意味着您的堆栈从哪里开始弹出,如果您没有基本条件,则递归调用将是无限的并导致堆栈内存已满并抛出堆栈溢出错误
    【解决方案3】:

    由于您希望以递归方式从 min 打印到 max,因此对于递归函数,有一个基本条件非常重要,您的代码将从该条件停止递归调用并开始弹出堆栈。因此,在下面的代码中,您正在调用具有 min 和 max 的递归函数 Range,这里 Range 函数将每次调用,直到满足基本条件并打印您的计数,每次调用为 +1 并继续推入堆栈。一旦满足基本条件,它就会开始弹出并且代码将成功结束。

    public static void main(String[] args) {
        // Range(min, max)
        Range(2, 10);
    }
    
    public static void Range(int count, int max) {
        System.out.println(count);
    
        // Base condition
        if(count >= max) return;
    
        // Recursive call
        Range(count + 1, max);
    }
    

    【讨论】:

      【解决方案4】:

      在递归方法中你需要做的第一件事是有一个终止条件。如果条件为真,则该方法终止。如果条件为假,则该方法会调用自身,但会更改其参数。在下面的代码中,实际上是相反的。如果条件为真,则方法调用自身,如果条件为假,则方法终止。

      public class Tester {
          private static void printNum(int num, int limit) {
              if (num <= limit) {
                  System.out.printf("%d ", num);
                  printNum(num + 1, limit);
              }
              else {
                  System.out.println();
              }
          }
      
          public static void main(String[] args) {
              printNum(2, 10);
          }
      

      该方法最初是从方法main() 调用的,带有起始编号和结束编号。在最初的调用中,num = 2 和 limit = 10。这意味着条件为真,因此数字 2 打印后有一个空格。然后调用相同的方法,但第一个参数等于 3,第二个参数相同,即 10。

      所以在第二次调用中,num = 3 和 limit = 10。然后该方法打印 3 并在其后添加一个空格,然后使用参数 4 和 10 调用自身。

      最终,printNum() 方法被调用,num = 11 和 limit = 10 这意味着条件 [if (num &lt;= limit) ] 为 false,因此该方法不会调用自身并打印换行符。一旦方法没有调用自己,递归就会停止。

      如果递归方法没有终止条件,它将继续调用自己。每次调用都需要内存来存储本地方法变量和其他东西。所以每次递归调用都意味着你的程序需要更多的内存。 Java 对可以进行的递归调用数量进行了限制。一旦超过该限制,Java 就会抛出 StackOverflowError 并强制终止您的程序。

      【讨论】:

      • 哇,谢谢你的解释,但我仍然不明白如何停止递归循环。有没有更简单的代码,我可以很容易地理解它是如何停止的,以及你说什么来停止你需要回调它的方法的递归循环?但这与您通过调用return自己执行方法不同吗?
      【解决方案5】:

      我知道的最简单的方法就是这样做。

      • 如果min &lt;= max 打印最小值并使用更新的最小值调用范围
      • 否则返回。
      range(2,10);
      
      public static void range(int min, int max) {
          if (min <= max) {
             System.out.print(min + " ");
             range(min+1, max);
          }
      }
      

      它是这样工作的。

      • 从主程序第一次调用。
      • 已输入范围。
      • 最小值 = 2,最大值 = 10
      • 是最小值
      • 是的,所以打印最小值为 2
      • 现在调用范围为 3 和 10(之前的最小 +1)
      • 输入范围
      • 最小值 = 3,最大值 = 10
      • 是最小值
      • 是的,所以打印最小值是 3
      • 现在调用范围为 4 和 10(之前的最小值 + 1)
      • 输入范围
      • 最小值 = 4,最大值 = 10
      • 如果最小值
      • 是的,所以打印最小值是 4
      • 现在调用范围为 5 和 10(之前的最小值 + 1)
      • 继续这种方式直到min &gt; max

      最终 min > max 并且整个调用堆栈将展开并返回到调用程序。

      【讨论】:

      • 在代码中为什么一定要+1range (min+1, max);
      • 因为我又在调用程序了。下次我调用它时,min 将是 3 并且将打印 3。然后是 4,然后是 5。当 min == max 时,它将开始通过调用堆栈返回并最终返回到第一次调用的位置。想想如果是这样。如果您简单地连续调用 range 方法 5 次,每次 min 增加 1 个值而没有递归,您将遍历这些值。但递归是程序调用自身的时候。
      • 我用解释修改了我的答案。
      • 我明白这有点清楚了,非常感谢@WJS
      猜你喜欢
      • 2014-03-22
      • 1970-01-01
      • 1970-01-01
      • 2016-11-25
      • 1970-01-01
      • 1970-01-01
      • 2016-08-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多