一个有意思的事情,写个程序输出从1到N的全排列。我们知道数学公式有N!种排列。但是计算机程序如何数出来呢。
可以用递归的思想解决这个问题。递归要有递归公式和退出条件。
- N=1
排列:[1] - N=2
排列:[12] [21] - N=3 : [123] [312] [213] [321] [132] [231]
... - 递归公式推导
假设排列1:N为af(N),我们现在要导出af(N)和af(N-1)的关系(公式)。
首先比较下af(3)和af(2)的差别,不难总结:
af(3) = 交换顺序(af(2),3),取并集(将3插入到af(2)各种排列不同的位置)
换成N,即:
af(N)=swap(af(N-1),N) U (instert(af(N-1),N)
递归退出条件就是N=1和2.
具体实现,这里使用R语言实现。
实现交换函数
swapf <- function(x,y){
# x, y vector
list(c(x,y),c(y,x))
}
- 执行实例
swapf(1,2)
[[1]]
[1] 1 2
[[2]]
[1] 2 1
swapf(1:2,3:4)
[[1]]
[1] 1 2 3 4
[[2]]
[1] 3 4 1 2
实现插入函数
insertf <- function(x,y){
# x vector,and y vector whith length one.
len = length(x)
if(len == 1) swapf(x,y) -> rt
if(len >= 2){
rt = list()
for(i in 1:(len-1)){
tmp = c(x[1:i],y,x[(i+1):len]);#print(tmp)
rt <- c(rt, list(tmp))
}
}
rt
}
- 执行实例
insertf(1:3,5)
[[1]]
[1] 1 5 2 3
[[2]]
[1] 1 2 5 3
insertf(1:3,5:6)
[[1]]
[1] 1 5 6 2 3
[[2]]
[1] 1 2 5 6 3
实现递归公式
af<-function(n){
if(n==1) return(list(1)) # 递归退出条件
if(n==2) return(swapf(1,2)) # 递归退出条件
lapply(af(n-1), swapf,n) %>% unlist(recursive = F) %>% c(sapply(af(n-1),insertf,n))
}
- 执行实例
af(1)
[[1]]
[1] 1
> af(2)
[[1]]
[1] 1 2
[[2]]
[1] 2 1
> af(3)
[[1]]
[1] 1 2 3
[[2]]
[1] 3 1 2
[[3]]
[1] 2 1 3
[[4]]
[1] 3 2 1
[[5]]
[1] 1 3 2
[[6]]
[1] 2 3 1
> af(4)
[[1]]
[1] 1 2 3 4
[[2]]
[1] 4 1 2 3
[[3]]
[1] 3 1 2 4
[[4]]
[1] 4 3 1 2
[[5]]
[1] 2 1 3 4
[[6]]
[1] 4 2 1 3
[[7]]
[1] 3 2 1 4
[[8]]
[1] 4 3 2 1
[[9]]
[1] 1 3 2 4
[[10]]
[1] 4 1 3 2
[[11]]
[1] 2 3 1 4
[[12]]
[1] 4 2 3 1
[[13]]
[1] 1 4 2 3
[[14]]
[1] 1 2 4 3
[[15]]
[1] 3 4 1 2
[[16]]
[1] 3 1 4 2
[[17]]
[1] 2 4 1 3
[[18]]
[1] 2 1 4 3
[[19]]
[1] 3 4 2 1
[[20]]
[1] 3 2 4 1
[[21]]
[1] 1 4 3 2
[[22]]
[1] 1 3 4 2
[[23]]
[1] 2 4 3 1
[[24]]
[1] 2 3 4 1