/*
打印一个字符串的全部排列
[a,b,c]
[0,1,2]
0a ->0 1b -> 0 2c ->0 谁来到0 位置 做决策
abc bac cba
1b ->1 2c ->1 谁来到1 位置 做决策,不要把已经放到0位置的 再调回来
abc acb
2c ->2 2b ->2
abc acb
1a->1 2c->1 1b ->b 2a ->1
bac bca cba cab
*/
func premution(str string) []string {
var res []string
if str == "" || len(str) == 0 {
return res
}
process([]byte(str),0,&res)
return res
}
//str[0...i-1]已经做好决定的
//str[i...]都有机会来到i位置
//i终止位置,str当前的样子就是一种结果 -> ans
func process(str []byte, i int,res *[]string) {
if i == len(str) {
*res = append(*res, string(str))
return //可加可不加
}
// 若果i 没到终止位置,从i 往后的所有位置都可以来到i位置(j,可以尝试来到i位置)
for j := i; j < len(str); j++ {
swap(str,i,j)
process(str,i+1,res)
swap(str,i,j) // 恢复现场,才能正确执行
}
}
func swap(str []byte,i,j int) {
str[i] , str[j] = str[j], str[i]
}
func TestPermutations(t *testing.T) {
fmt.Println(premution("abac"))
}
/*
打印一个字符串的全部排列 要求不出现重复的排列
分支限界
*/
func TestPremution2(t *testing.T) {
fmt.Println(premution2("abac"))
}
func premution2(str string) []string {
var res []string
if str == "" || len(str) == 0 {
return res
}
process_2([]byte(str),0,&res)
return res
}
//str[0...i-1]已经做好决定的
//str[i...]都有机会来到i位置
//i终止位置,str当前的样子就是一种结果 -> ans
func process_2(str []byte, i int,res *[]string) {
if i == len(str) {
*res = append(*res, string(str))
return // 可加可不加
}
visit := [26]bool{} //非共享,剪枝 --> 分支限定
// 若果i 没到终止位置,从i 往后的所有位置都可以来到i位置(j,可以尝试来到i位置)
for j := i; j < len(str); j++ {
if !visit[str[j]-'a'] {
visit[str[j]-'a'] = true
swap(str, i, j)
process_2(str, i+1, res)
swap(str, i, j) // 恢复现场,才能正确执行
}
}
}
// 用一个变量就能解决问题
func premution3(str string) []string {
var res []string
if str == "" || len(str) == 0 {
return res
}
process_3([]byte(str),0,&res)
return res
}
func process_3(str []byte, i int,res *[]string) {
if i == len(str) {
*res = append(*res, string(str))
return // 可加可不加
}
visit := 0 //非共享,剪枝 --> 分支限定
// 若果i 没到终止位置,从i 往后的所有位置都可以来到i位置(j,可以尝试来到i位置)
for j := i; j < len(str); j++ {
if visit >> (str[j]-'a') &1 == 0 {
visit |= 1 << (str[j]-'a')
swap(str, i, j)
process_3(str, i+1, res)
swap(str, i, j) // 恢复现场,才能正确执行
}
}
}
func TestPremution3(t *testing.T) {
fmt.Println(premution3("aaaa"))
}
递归——打印一个字符串的全排列
最新推荐文章于 2023-01-04 21:55:01 发布