全排列
发现了一个种全排列的新写法,类似于洗牌
原始写法
按照我以前的写法,如下:
package main
import "fmt"
func getPerm(ori []int, cur []int, pos int, vis []bool, resP *[][]int) {
if pos == len(ori) {
*resP = append(*resP, append([]int{}, cur...))
return
}
for i := 0; i < len(ori); i++ {
if !vis[i] {
vis[i] = true
cur[pos] = ori[i]
getPerm(ori, cur, pos+1, vis, resP)
vis[i] = false
}
}
}
func main() {
ori := []int{11, 22, 33, 44, 55}
res := make([][]int, 0)
getPerm(ori, make([]int, len(ori)), 0, make([]bool, len(ori)), &res)
for i := 0; i < len(res); i++ {
fmt.Print(res[i])
fmt.Printf("\n")
}
}
新写法
模拟洗牌
本质是
任何一个置换都可以表示为不相交轮换的乘积,若不计因子的顺序,其分解式是唯一的。
package main
import "fmt"
func nextPerm(p []int) {
for i := len(p) - 1; i >= 0; i-- {
if i == 0 || p[i]+1+i < len(p) {
p[i]++
return
}
p[i] = 0
}
}
func getPerm(ori []int, p []int) []int {
cur := append([]int{}, ori...)
for k, v := range p {
cur[k], cur[k+v] = cur[k+v], cur[k]
}
return cur
}
func main() {
ori := []int{11, 22, 33, 44, 55}
for p := make([]int, len(ori)); p[0] < len(p); nextPerm(p) {
cur := getPerm(ori, p)
fmt.Println(cur)
}
}