【问题标题】:Java Recursion printing asterisks from one method callJava Recursion 从一个方法调用中打印星号
【发布时间】:2013-04-16 01:07:16
【问题描述】:

我有一个在 Java 中介绍递归的作业,但我遇到了障碍。该赋值需要一种递归方法来输出多个星号的行数,具体取决于传递给它的整数值。例如,如果将 4 作为变量 n 传入,则输出将有一个星号的第一行,下一行 2 个星号,下一个 3 个星号,下一个 4,然后是 4、3、2 和 1。

我已经能够完成输出的前半部分(虽然不确定它是否是最佳的),但不知道如何让方法反转回来。这一切都可以在一个方法调用中完成,并将变量 (n) 传递给方法。

这是我目前的方法:

    public static void myMethod(int n)
    {       
    if (n <= 1) {
            System.out.print("*");          
    } else {
        myMethod(n - 1);
        for (int i = 0; i < n; i++) {
            System.out.print("*");
        }
    }

    System.out.print("\n"); // new line
    }

它是从 main 调用的:

    myMethod(n);

所以我有一个 for 循环,它会在同一行 'n' 次打印一个星号。在 for 循环之后,它继续到下一行并循环,改变 n。但我不知道如何让它反转。

我的方法从方法中打印出来。我的导师向我展示了一个示例版本,它传递了 2 个变量 (n) 和一个空字符串。

    public static String myMethod(int n, String displayStr) {       
        String currentStr = "";

    for (int i = 0; i < n; i++)
        currentStr += "*";
        currentStr += "\n";

        if (displayStr == null){
            return myMethod((n - 1), currentStr);   
        } // end base case

        else if (n > 0){
            return myMethod((n - 1), (currentStr + displayStr + currentStr));
        }

        else {
            return displayStr;
        }
    } // end recursion method myMethod

他的版本使用以下代码行从 main 打印:

    System.out.println(myMethod(n, null));

我已经尝试过他的版本,它会在侧面打印三角形,但最大的线只打印一次而不是两次。我花了一整天的时间试图改变他在中间添加一个重复的行,并且开始认为这是不可能的。

任何帮助将不胜感激。我对此完全停滞不前。

【问题讨论】:

  • 如果你想放置一个双n大小的线,你应该看看n是最大的情况(第一次调用)——当displayStr == null

标签: java recursion


【解决方案1】:

将方法签名更改为public static void myMethod(int n, boolean reversed),其中reversed 初始化为false,但在打印n 星号时翻转为true。在方法内部,如果reversed 为真,则反转您的逻辑。

【讨论】:

    【解决方案2】:

    您基本上只需要打印出当前行,然后进行递归调用,然后再次打印该行。这样,您就可以在上升的过程中积累堆栈,然后在下降的过程中再次积累。

    这是一个使用 2 个参数的示例,一个是最大长度,另一个是递归的迭代器。

    // bootstrap method to start the recursion
    public static void myMethod(int length)
    {
        myMethod(length, length);
    }
    
    public static void myMethod(int length, int i)
    {
        if (i > 0)
        {
            int rowLength = length - i + 1;
    
            printRow(rowLength, '*');
    
            myMethod(length, i - 1);
    
            printRow(rowLength, '*');
        }
    }
    
    public static void printRow(int length, char symbol)
    {
        for (int i = 0; i < length; i++)
            System.out.print(symbol);
        System.out.println();
    }
    

    【讨论】:

    • 好吧,这似乎是有道理的。我的教授喜欢教课本的幻灯片,而我通过动手实验学得更好。我也试试这个!非常感谢!
    【解决方案3】:

    因为输出计数向上(不是*向下到零),你必须传入星号的数量来打印最大数量,所以终止条件可以成立。

    此外,您的方法的伪代码是:

    • 如果 n > 最大返回(终止条件)
    • 打印 n 个星号
    • 递归调用 n + 1
    • 打印 n 个星号

    如果您传入的不是要打印的当前长度,而是星号字符串,则可以实现大量代码简化,因此您的(私有)递归方法可以很简单:

    private static void myMethod(int n, String s) {
        if (s.length() < n) return;
        System.out.println(s);
        myMethod(n, s + "*");
        System.out.println(s);
    }
    

    然后,设置初始条件的公共方法是:

    public static void myMethod(int n) {
        myMethod(n, "*");
    }
    

    恕我直言,一个具有良好代码密度的优雅实现。

    【讨论】:

    • 这非常有效,谢谢!我的教授要求我们只使用一种方法,但是当我开始向他询问有关他的示例的问题时,他无法真正回答,所以我不确定他是否也完全解决了这个问题。
    • 当终止条件为任意时,必须将 atate 传递给下一个调用。如果您想打印4 3 2 1 1 2 3 4,您只需要一种方法,因为在编译时已知终止条件为 n=0。所以你的递归方法必须有两个参数;没有办法绕过它。这种代码模式很常见——私有代码传递它需要的任何额外参数,公共 API 提供一个简单的 API,设置初始状态并隐藏递归实现的复杂性。基本上,你的“教授”是错的。
    猜你喜欢
    • 2020-06-07
    • 1970-01-01
    • 2023-03-28
    • 2013-03-18
    • 1970-01-01
    • 1970-01-01
    • 2014-10-06
    • 2012-09-05
    相关资源
    最近更新 更多