找到字符串的所有排列

时间:2014-11-03 17:52:23

标签: java recursion

我一直试图了解它是如何工作的,但由于我对java的了解有限,我没有。以下是将产生排列的代码:

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, n));
    }
}

//主:

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

我试着看看很多stackoverflow posts,但是他们没有详细说明这是如何工作的

3 个答案:

答案 0 :(得分:1)

这种方法的想法是使用递归来查找字符串的所有排列。为了使递归起作用,它必须根据同样的问题定义问题,稍微减少。

字符串的排列是什么?让我们看一下字符串&#34; abc&#34;:

的示例
abc
acb
bac
bca
cab
cba

我们注意到的是,排列就像选择其中一个字母作为第一个,然后对其余字母做同样的事情。也就是说,如果我们挑选一个&#39;首先,我们有排列:

bc
cb

如果我们选择&#39; b&#39;首先,我们有

ac
ca

如果我们选择&#39; c&#39;我们有

ab
ba

因此,我们可以根据自身(减少)来定义我们的问题。因此,为了置换具有n个字符的字符串,我们需要选择每个字符,确定它是第一个字符,然后将剩余字符串的所有排列附加到第一个字母。这意味着我们必须找到长度为n-1个字符的字符串的所有排列,并将其附加到我们选择的第一个字母。

所以,

  • 查找n个字符串的排列:
  • 遍历字符串的所有字符
    • 选择我们正在查看的当前角色作为第一个角色
    • 将所有剩余字符作为字符串(长度现在为n-1)
    • 查找所有(n-1)个字符串的排列
    • 将每个人添加到我们首先选择的角色。

但我们什么时候停止?我们到达一个空字符串时停止,因为它没有排列。

你的程序正是这样做的,但是因为它只想打印排列,而不是收集它们,它所做的是保留在递归的上层完成的第一个字母的所有选择。这些是从递归的上层传递的。这样,当我们得到一个空字符串时,prefix包含一系列特定的首字母选择。由于没有其他任何东西可以置换,我们可以打印出我们得到的东西。

当我们从任何级别的递归返回时,当前级别知道已经打印了当前选择的第一个字符的所有排列。所以它移动到下一个第一个角色,并再次传递所有选择到目前为止。同样,它下面的所有级别都会添加它们的第一个字母,直到字符串为空。

在顶层你必须用空前缀来调用它,因为当然,你还没有做出任何第一个字符选择。让我们看看如果我们称之为排列会发生什么(&#34;&#34;,&#34; abc&#34;):

  • 1级选择a,呼叫排列(&#34; a&#34;,&#34; bc&#34;)
    • 2级选择b,呼叫排列(&#34; ab&#34;,&#34; c&#34;)
      • 3级选择c,呼叫排列(&#34; abc&#34;,&#34;&#34;)
        • 等级4有一个空字符串,因此它会打印 abc
      • 等级3没有其他选择。
    • 2级选择c,呼叫排列(&#34; ac&#34;,&#34; b&#34;)
      • 3级选择b,呼叫排列(&#34; acb&#34;,&#34;&#34;)
        • 等级4有一个空字符串,因此它会打印 acb
      • 等级3没有其他选择
    • 等级2没有其他选择
  • 1级选择b,呼叫排列(&#34; b&#34;,&#34; ac&#34;)
    • 2级选择a,呼叫排列(&#34; ba&#34;,&#34; c&#34;)
      • 3级选择c,呼叫排列(&#34; bac&#34;,&#34;&#34;)
        • 等级4有一个空字符串,因此它会打印 bac
      • 等级3没有其他选择
    • 2级选择c,呼叫排列(&#34; bc&#34;,&#34; a&#34;)
      • 3级选择a,呼叫排列(&#34; bca&#34;,&#34;&#34;)
        • 等级4有一个空字符串,因此它会打印 bca
      • 等级3没有其他选择
    • 等级2没有其他选择
  • 1级选择c,呼叫排列(&#34; c&#34;,&#34; ab&#34;)
    • 2级选择a,呼叫排列(&#34; ca&#34;,&#34; b&#34;)
      • 3级选择b,呼叫排列(&#34; cab&#34;,&#34;&#34;)
        • 等级4有一个空字符串,因此它会打印 cab
      • 等级3没有其他选择
    • 2级选择b,呼叫排列(&#34; cb&#34;,&#34; a&#34;)
      • 3级选择a,呼叫排列(&#34; cba&#34;,&#34;&#34;)
        • 等级4有一个空字符串,因此它会打印 cba
      • 等级3没有其他选择
    • 等级2没有其他选择
  • 等级1没有其他选择

答案 1 :(得分:0)

这个想法非常简单。

  1. permutation将打印str前面prefix的每个排列。
  2. 如果str为空,则唯一要打印的是prefix本身。
  3. 如果 为空,那么我们可以将问题分解为一组子问题,每个子问题都会稍长prefix&amp;通过将str的不同字符移动到str的末尾来缩短prefix,并打印每种组合的所有排列。 (因为我们在str为空时停止递归,这使我们更接近发生的事情。)
  4. 请注意,如果有任何重复的字符,结果中会有重复。

答案 2 :(得分:0)

permutation是一个递归函数,这意味着它是一个调用自身的方法。 因为我们不希望方法在连续循环中永远运行,所以我们需要提供基本情况,这意味着导致方法退出而不调用自身的条件。通过跟随样本值,这些方法更容易理解。例如,如果我们尝试permutation("", "a"),代码将按此顺序运行(n是str的长度):

permutation("", "a")// n=1 so loop through "a" 
==>permution("a", "")// n=0 so print prefix "a" and exit

现在尝试排列(“”,“ab”),我们将:

permutation("", "ab")// n=2 so loop through "ab"
==>permutation("a", "b")// n=1 so loop through "b"
====>permution("ab", "")// n=0 print prefix "ab" and exit
==>permutation("b", "a")// n=1 so loop through "a"
====>permution("ba", "")// n=0 print prefix "ba" and exit