3步实现从1到N的全排列——数据分析师不懂黑科技

一个有意思的事情,写个程序输出从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

你可能感兴趣的:(3步实现从1到N的全排列——数据分析师不懂黑科技)