【问题标题】:How does recursion work in a permutation?递归如何在排列中工作?
【发布时间】:2020-04-07 06:09:13
【问题描述】:

我正在查看编写为here 的置换程序。代码如下所示:

public static void main(String[] args) {
    permutation("", "CAT");
}

private static void permutation(String prefix, String str) {
    int n = str.length();
    if (n == 0) {
        System.out.println(prefix);
    } else {
        for (int i = 0; i < n; i++) {
            permutation(prefix + str.charAt(i), str.substring(0, i) + str.substring(i + 1));
        }
    }
}

对于单词 CAT,我得到以下输出:

号召性用语
行动
空中交通管制
三氯乙烷
交警

我可以追溯递归的步骤并了解它是如何获得 CAT 和 CTA 的,但我看不出它是如何继续进行的。在 n == 0(这是基本情况)之后,一切都应该停止(这将在我们获得 CTA 之后发生)。

其他来源:
我阅读了here 的解释,但我仍然无法理解它是如何继续进行的。我觉得我得到了递归的概念。我可以盲目地使用它,但我想了解它是如何在这里工作的。

还有另一种排列递归的版本here,但那是使用回溯,我理解的更好一些。这是我不明白的尾递归。

问题:
有人可以解释一下递归是如何工作的,以便我们在上面的示例中通过 CTA 吗?这不是家庭作业。我只是在研究不同的计划并通过一些技能培养者来工作。

谢谢!

【问题讨论】:

    标签: algorithm recursion


    【解决方案1】:

    让我们看看第一个调用生成了什么:

    ("" + str.charAt(0), str.substring(0, 0) + str.substring(0 + 1))
    p("C", "AT")
    
    ("" + str.charAt(1), str.substring(0,1) + str.substring(1 + 1))
    p("A", "CT")
    
    ("" + str.charAt(2), str.substring(0, 2) + str.substring(2 + 1))
    p("T", "CA")
    

    每次调用都会提取str 的每个字母并将其添加到当前前缀中。第一次调用将原始字符串的每个字母作为排列的开始。然后,对于每个这样的排列,算法提取剩余后缀的每个字母并将其添加到累积前缀中,以便探索所有可能性:

    C AT
        CA T
        CT A
            "CAT"
            "CTA"
    
    A CT
        AC T
        AT C
            "ACT"
            "ATC"
    
    T CA
        TC A
        TA C
             "TCA"
             "TAC"
    

    【讨论】:

    • 感谢您如此清晰透彻的解释!
    【解决方案2】:

    记住每个递归调用的状态(每个局部变量和参数的值)。在返回CAT 后只有一个呼叫结束,其他呼叫从中断处继续。

    将每个递归调用视为对一个全新函数的调用,该函数恰好做了同样的事情。

    这就是你的函数的执行方式。如果您还编写了每个局部变量的值(在您的情况下它只是 i 和参数),这可能会有所帮助。我只是写了什么叫什么。

    p("", "CAT") -> p("C", "AT") -> p("CA", "T") -> p("CAT", "") -> CAT and return
                                                 -> return
                                 -> p("CT", "A") -> p("CTA", "") -> CTA and return
                                                 -> return
                                 -> return
                 -> p("A", "CT") -> ...
    

    【讨论】:

    • 所以,我不确定这是否是正确的解释方式,但我会尝试。我从 p (x,y) 开始,然后开始研究基本情况。当我正在研究基本情况时,我正在“返回”另一个函数。对于每个函数 p(x*,y*),它都说:“我将自己一直工作到基本情况。”所以,它从顶部开始,一直工作到基本情况,但在这样做的过程中,它有一大堆这些功能的其他变体。因此,在它到达第一个函数的基本情况后,它会转到下一个函数并做同样的事情。
    【解决方案3】:

    要理解递归,我们必须从“阶乘递归”开始

    【讨论】:

      猜你喜欢
      • 2016-03-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-14
      • 2015-10-26
      • 2020-02-06
      • 2018-03-18
      相关资源
      最近更新 更多