【问题标题】:How do I write a recursive algorithm for permutations?如何为排列编写递归算法?
【发布时间】:2013-04-30 13:02:50
【问题描述】:

我的问题涉及在给定整数输入的情况下输出排列的递归方式。 每个整数代表一组字母,就像电话的键盘一样。

所以集合看起来像:

1: {}
2: {"A", "B", "C"}
3: {"D", "E", "F"}
4: {"G", "H", "I"}
etc...

我需要生成给定一系列数字的代码,该代码将输出字母的所有排列。

因此,输入 123 将输出: AD、AE、AF、BD、BF、CD、CE、CF

最好使用伪代码,而且我对 Java 还算流利,但欢迎提供任何帮助。

请随时就这个问题的提问方式提供反馈,我仍然不确定如何在此处正确发布。

【问题讨论】:

  • 为什么要递归?迭代不是更容易吗?
  • @jsobo 算法要求是递归的,我可以做一个迭代没有太多麻烦,但递归对我来说仍然是一个巨大的延伸。

标签: java recursion permutation pseudocode


【解决方案1】:

你可以有一个非递归函数,它接受两个Set 并返回一个排列的Set

private Set<String> getPermutations(Set<String> a, Set<String> b){
...
}

然后你可以有一个递归函数

public Set<String> recursivePermutations(List<Set<String>> sets){
    if(sets.size() ==2){
        return getPermutations(sets.get(0), sets.get(1));
    }else{
        return getPermutations(sets.get(0),recursivePermutations(sets.sublist(1,sets.size()-1));
    }
}

当您的列表中只有 1 个元素时,您可能需要添加安全防护,如果您真的不需要列表,也可以使用 Collection

编辑

递归背后的主要思想是有两种情况:一种是简单的情况(当你只有两个集合时),你可以应用非递归方法,另一种是递归的情况,你必须再次对问题应用函数缩小尺寸。

在我的示例中,如果您有 2 个以上的集合,则递归地重新应用相同的函数,但集合数量较少(该函数应用于第一个元素和其余集合)。

假设您首先将您的函数应用于n 集合的列表。第二次应用函数时,您将获得n-1 的列表,依此类推,直到达到n=2 时的情况。在这种情况下,您不需要使用递归,因为这是一个简单的情况。

【讨论】:

  • 如果有问题我也可以详细说明getPermutations方法
  • 我不太明白你的递归函数发生了什么。请原谅我的无知...
  • @SamSam 好的,让我改进一下答案
  • 我能理解你的所作所为,谢谢。这个方法需要一个列表,这是一个什么样的列表?链接?编译器抱怨List 不是泛型,但随后返回并要求泛型类型。我认为这意味着我需要一个包含通用元素的列表?
  • @SamSam 在 Java 中是的 List 是一个接口。此接口最常见的实现之一是ArrayListLinkedList。对于这个特定的示例,您可以选择其中任何一个。所以你可以做类似List&lt;A&gt; list = new ArrayList&lt;A&gt;()
【解决方案2】:

这是F#的一种方法:

open System
open System.Collections.Generic

let pad = new Dictionary<int, string>()
pad.Add(2, "A,B,C")
pad.Add(3, "D,E,F")
pad.Add(4, "G,H,I")

let permutations = new List<string>()

let rec permute(digits: int list, alphas: string list) =    
    if List.length digits > 0 && List.length alphas = 0 then
        permute(digits, ["#"] |> List.append (pad.[digits.[0]].Split([|','|]) |> List.ofArray))
    else
        match alphas with
        | [_] ->
            match digits with
            | h::t -> permute(t, [])
            | _ -> ()
        | h::t ->
            for i = 0 to List.length alphas - 2 do
                permutations.Add(h + alphas.[i])
            for j = 1 to List.length digits - 1 do
                let others = pad.[digits.[j]].Split([|','|])
                for o in others do
                    permutations.Add(h + o)
            permute(digits, t)
        | _ -> ()

permute([2;3;4;], [])

seq { 
    for o in permutations do 
        yield o
        yield o.[1].ToString() + o.[0].ToString()
}
|> Seq.distinct
|> Seq.sort 
|> Seq.iter(fun s -> Console.WriteLine(s))
;;

输出

[2; 3; 4]
[]


[2; 3; 4]
[A; B; C; ... ]

AA
AB
AC
AD
AE
AF
AG
AH
AI

[2; 3; 4]
[B; C; #]

BB
BC
BD
BE
BF
BG
BH
BI

[2; 3; 4]
[C; #]

CC
CD
CE
CF
CG
CH
CI

[2; 3; 4]
[#]


[3; 4]
[]


[3; 4]
[D; E; F; ... ]

DD
DE
DF
DG
DH
DI

[3; 4]
[E; F; #]

EE
EF
EG
EH
EI

[3; 4]
[F; #]

FF
FG
FH
FI

[3; 4]
[#]


[4]
[]


[4]
[G; H; I; ... ]

GG
GH
GI

[4]
[H; I; #]

HH
HI

[4]
[I; #]

II

[4]
[#]


[]
[]

AA
AB
AC
AD
AE
AF
AG
AH
AI
BA
BB
BC
BD
BE
BF
BG
BH
BI
CA
CB
CC
CD
CE
CF
CG
CH
CI
DA
DB
DC
DD
DE
DF
DG
DH
DI
EA
EB
EC
ED
EE
EF
EG
EH
EI
FA
FB
FC
FD
FE
FF
FG
FH
FI
GA
GB
GC
GD
GE
GF
GG
GH
GI
HA
HB
HC
HD
HE
HF
HG
HH
HI
IA
IB
IC
ID
IE
IF
IG
IH
II

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-06
    • 2012-10-24
    • 2022-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-01
    相关资源
    最近更新 更多