feat(Go-Tool):2021/03/26: 新增全排列的递归实现、字典序实现、递增进制位实现、递减进制位实现

This commit is contained in:
Huangzj
2021-03-26 09:13:34 +08:00
parent 00ada130fa
commit 092ab58276
10 changed files with 479 additions and 0 deletions
+56
View File
@@ -0,0 +1,56 @@
/*
* @Author : huangzj
* @Time : 2021/3/22 15:29
* @Description
*/
package FullPermutation
import (
sort2 "Go-Tool/util/sort"
)
//字典序获取全排列
func (per *Permutation) DictionaryOrder(b []byte) {
//先排序
sort2.QuickSortByte(b, 0, len(b)-1)
for {
bef := 0
afr := 0
result := make([]byte, len(b))
copy(result, b)
per.bytes = append(per.bytes, result)
//从右往左找到第一个左边比右边小的数字
for bef = len(b) - 2; ; bef-- {
if bef < 0 {
return
}
if b[bef] < b[bef+1] {
break
}
}
//知道q的位置之后
//从q开始向右边查找比位置q的数字大的第一个数字的位置
for afr = len(b) - 1; afr > 0; afr-- {
if b[afr] > b[bef] {
break
}
}
//交换两个数字
b[bef], b[afr] = b[afr], b[bef]
//把后面的数字进行转置成递增顺序
b = per.Reverse(b, bef+1, len(b)-1)
}
}
func (per *Permutation) Reverse(b []byte, start, end int) []byte {
for start <= end {
b[start], b[end] = b[end], b[start]
start++
end--
}
return b
}
@@ -0,0 +1,52 @@
/*
* @Author : huangzj
* @Time : 2021/3/22 15:29
* @Description
*/
package FullPermutation
import (
"fmt"
"testing"
)
func TestDictionaryOrder(t *testing.T) {
p := NewPermutation()
p.DictionaryOrder([]byte("1234"))
fmt.Println()
for _, bs := range p.bytes {
fmt.Println(string(bs))
}
p.Reset()
p.DictionaryOrder([]byte("12345"))
fmt.Println()
for _, bs := range p.bytes {
fmt.Println(string(bs))
}
p.Reset()
p.DictionaryOrder([]byte("abcde"))
fmt.Println()
for _, bs := range p.bytes {
fmt.Println(string(bs))
}
p.Reset()
p.DictionaryOrder([]byte("abcdea"))
fmt.Println()
for _, bs := range p.bytes {
fmt.Println(string(bs))
}
p.Reset()
}
func TestPermutation_Reverse(t *testing.T) {
p := NewPermutation()
fmt.Println(p.Reverse([]byte{1, 2, 3, 4}, 0, 3))
fmt.Println(p.Reverse([]byte{1, 2, 3, 4, 5}, 0, 4))
fmt.Println(p.Reverse([]byte{1, 2, 3, 4, 5, 6}, 0, 5))
fmt.Println(p.Reverse([]byte{1, 2, 3, 4, 5, 6, 7}, 0, 6))
}
+71
View File
@@ -0,0 +1,71 @@
/*
* @Author : huangzj
* @Time : 2021/3/23 17:06
* @Description
*/
package FullPermutation
func DigitDecreases(b []int) [][]int {
result := make([][]int, 0)
bit := make([]int, len(b)-1)
sum := 1
//计算中的结果数,阶乘
for i := 1; i <= len(b); i++ {
sum = sum * i
}
for i := 0; i < sum; i++ {
result = append(result, getRangeBySpace1(b, bit))
bit = decreaseBit(bit)
}
return result
}
//根据递增进制位,并且根据【数空格法】在原来的数组中求得全排列的一种可能实现
//origin 原始数组
//increaseBit 递增进制位,比原始数组长度小1,这里通过数组实现,更简单
func getRangeBySpace1(origin []int, increaseBit []int) []int {
permutation := make([]int, len(origin))
flag := make(map[int]bool, 0)
//排列数组从左往右,即从大到小
for i := 0; i < len(origin)-1; i++ {
p := increaseBit[i] //从右到左,对应数字应该填充的位置
j := len(origin) - 1 //该数字在本次排列的位置
for ; ; j-- {
//该位置未被填充
if !flag[j] {
p--
}
//找到对应位置需要推出循环
if p < 0 {
flag[j] = true
break
}
}
permutation[j] = origin[i]
}
for i := 0; i < len(origin); i++ {
if !flag[i] {
permutation[i] = origin[len(origin)-1]
}
}
return permutation
}
//递减进制位
//每次加一,计算新的数组结果
func decreaseBit(bit []int) []int {
//数组下标从小到大,进制位从大到小
for i := 0; i < len(bit); i++ {
if bit[i]+1 >= len(bit)+1-i {
bit[i] = (bit[i] + 1) % (len(bit) + 1 - i)
} else {
bit[i] += 1
break
}
}
return bit
}
@@ -0,0 +1,59 @@
/*
* @Author : huangzj
* @Time : 2021/3/23 19:53
* @Description
*/
package FullPermutation
import (
"fmt"
"testing"
)
func TestDecreaseBit(t *testing.T) {
bit := []int{0, 0}
for i := 0; i < 6; i++ {
fmt.Println(bit)
bit = decreaseBit(bit)
}
fmt.Println()
bit = []int{0, 0, 0}
for i := 0; i < 24; i++ {
fmt.Println(bit)
bit = decreaseBit(bit)
}
fmt.Println()
bit = []int{0, 0, 0, 0}
for i := 0; i < 120; i++ {
fmt.Print(bit)
bit = decreaseBit(bit)
}
}
func TestGetRangeBySpace1(t *testing.T) {
fmt.Println(getRangeBySpace1([]int{1, 2, 3}, []int{0, 0}))
fmt.Println(getRangeBySpace1([]int{1, 2, 3}, []int{1, 0}))
fmt.Println(getRangeBySpace1([]int{1, 2, 3}, []int{2, 0}))
fmt.Println(getRangeBySpace1([]int{1, 2, 3}, []int{0, 1}))
fmt.Println(getRangeBySpace1([]int{1, 2, 3}, []int{1, 1}))
fmt.Println(getRangeBySpace1([]int{1, 2, 3}, []int{2, 1}))
fmt.Println(getRangeBySpace1([]int{1, 2, 3, 4, 5}, []int{0, 0, 0, 0}))
fmt.Println(getRangeBySpace1([]int{1, 2, 3, 4, 5}, []int{0, 0, 0, 1}))
fmt.Println(getRangeBySpace1([]int{1, 2, 3, 4, 5}, []int{4, 3, 2, 1}))
fmt.Println(getRangeBySpace1([]int{1, 2, 3, 4, 5}, []int{3, 0, 0, 0}))
fmt.Println(getRangeBySpace1([]int{1, 2, 3, 4, 5}, []int{1, 3, 2, 1}))
fmt.Println(getRangeBySpace1([]int{1, 2, 3, 4, 5, 6, 7}, []int{3, 4, 2, 2, 2, 1}))
}
func TestDigitDecrease(t *testing.T) {
fmt.Println(DigitDecreases([]int{1, 2, 3}))
fmt.Println(DigitDecreases([]int{20, 50, 30, 67}))
fmt.Println(DigitDecreases([]int{20, 50, 30, 99, 18213}))
fmt.Println(DigitDecreases([]int{20, 50, 30, 78321, 2321, 432}))
}
+71
View File
@@ -0,0 +1,71 @@
/*
* @Author : huangzj
* @Time : 2021/3/23 17:05
* @Description
*/
package FullPermutation
func DigitIncrease(b []int) [][]int {
result := make([][]int, 0)
bit := make([]int, len(b)-1)
sum := 1
//计算中的结果数,阶乘
for i := 1; i <= len(b); i++ {
sum = sum * i
}
for i := 0; i < sum; i++ {
result = append(result, getRangeBySpace(b, bit))
bit = increaseBit(bit)
}
return result
}
//根据递增进制位,并且根据【数空格法】在原来的数组中求得全排列的一种可能实现
//origin 原始数组
//increaseBit 递增进制位,比原始数组长度小1,这里通过数组实现,更简单
func getRangeBySpace(origin []int, increaseBit []int) []int {
permutation := make([]int, len(origin))
flag := make(map[int]bool, 0)
//排列数组从左往右,即从大到小
for i := len(origin) - 1; i > 0; i-- {
p := increaseBit[i-1] //从右到左,对应数字应该填充的位置
j := len(origin) - 1 //该数字在本次排列的位置
//中介数计算从左到右,即从大到小
for ; ; j-- {
//该位置未被填充
if !flag[j] {
p--
}
//找到对应位置需要推出循环
if p < 0 {
flag[j] = true
break
}
}
permutation[j] = origin[i]
}
for i := 0; i < len(origin); i++ {
if !flag[i] {
permutation[i] = origin[0]
}
}
return permutation
}
//递增进制位
//根据递增进制位进行+1操作,返回递增的结果
func increaseBit(bit []int) []int {
//最开始是从二进制开始
for i, num := range bit {
if num+1 >= i+2 {
bit[i] = (num + 1) % (i + 2)
} else {
bit[i] = num + 1
break
}
}
return bit
}
@@ -0,0 +1,57 @@
/*
* @Author : huangzj
* @Time : 2021/3/23 19:54
* @Description
*/
package FullPermutation
import (
"fmt"
"testing"
)
func TestGetRangeBySpace(t *testing.T) {
fmt.Println(getRangeBySpace([]int{1, 2, 3}, []int{0, 0})) //123
fmt.Println(getRangeBySpace([]int{1, 2, 3}, []int{1, 0})) //
fmt.Println(getRangeBySpace([]int{1, 2, 3}, []int{0, 1})) //
fmt.Println(getRangeBySpace([]int{1, 2, 3}, []int{1, 1})) //
fmt.Println(getRangeBySpace([]int{1, 2, 3}, []int{0, 2})) //
fmt.Println(getRangeBySpace([]int{1, 2, 3}, []int{1, 2})) //321
//fmt.Println(getRangeBySpace([]int{1, 2, 3, 4, 5}, []int{0, 0, 0, 0})) //12345
//fmt.Println(getRangeBySpace([]int{1, 2, 3, 4, 5}, []int{0, 0, 0, 1})) //21354
fmt.Println(getRangeBySpace([]int{1, 2, 3, 4, 5}, []int{1, 2, 3, 4})) //54321
fmt.Println(getRangeBySpace([]int{1, 2, 3, 4, 5}, []int{0, 0, 0, 3})) //12534
fmt.Println(getRangeBySpace([]int{1, 2, 3, 4, 5}, []int{1, 2, 3, 1})) //43251
fmt.Println(getRangeBySpace([]int{1, 2, 3, 4, 5, 6, 7}, []int{1, 2, 2, 2, 4, 3})) //3647521
}
func TestIncreaseBit(t *testing.T) {
bit := []int{0, 0}
for i := 0; i < 6; i++ {
fmt.Println(bit)
bit = increaseBit(bit)
}
fmt.Println()
bit = []int{0, 0, 0, 0}
for i := 0; i < 120; i++ {
bit = increaseBit(bit)
fmt.Println(bit)
}
bit = []int{0, 0, 0}
for i := 0; i < 24; i++ {
bit = increaseBit(bit)
fmt.Println(bit)
}
}
func TestDigitIncrease(t *testing.T) {
fmt.Println(DigitIncrease([]int{1, 2, 3}))
fmt.Println(DigitIncrease([]int{20, 50, 30, 67}))
fmt.Println(DigitIncrease([]int{20, 50, 30, 99, 18213}))
fmt.Println(DigitIncrease([]int{20, 50, 30, 78321, 2321, 432}))
}
+39
View File
@@ -0,0 +1,39 @@
/*
* @Author : huangzj
* @Time : 2021/3/22 11:09
* @Description
*/
package FullPermutation
type Permutation struct {
bytes [][]byte
}
func NewPermutation() *Permutation {
return &Permutation{
bytes: [][]byte{},
}
}
func (per *Permutation) Recursion(b []byte, start int) {
//递归交换到最后一个位置结束
if start == len(b)-1 {
bCopy := make([]byte, len(b))
copy(bCopy, b)
per.bytes = append(per.bytes, bCopy)
}
for i := start; i < len(b); i++ {
//交换固定位置
b[i], b[start] = b[start], b[i]
//固定某一个数字位置,递归后面的其他数字
per.Recursion(b, start+1)
//还原固定位置,进行下一次操作
b[i], b[start] = b[start], b[i]
}
}
func (per *Permutation) Reset() {
per.bytes = [][]byte{}
}
+45
View File
@@ -0,0 +1,45 @@
/*
* @Author : huangzj
* @Time : 2021/3/22 11:22
* @Description
*/
package FullPermutation
import (
"fmt"
"testing"
)
func TestRecursion(t *testing.T) {
p := NewPermutation()
p.Recursion([]byte("123"), 0)
fmt.Println()
for _, bs := range p.bytes {
fmt.Println(string(bs))
}
p.Reset()
p.Recursion([]byte("12345"), 0)
fmt.Println()
for _, bs := range p.bytes {
fmt.Println(string(bs))
}
p.Reset()
p.Recursion([]byte("abcde"), 0)
fmt.Println()
for _, bs := range p.bytes {
fmt.Println(string(bs))
}
p.Reset()
p.Recursion([]byte("abcdea"), 0)
fmt.Println()
for _, bs := range p.bytes {
fmt.Println(string(bs))
}
p.Reset()
}