分治法应用——全排列

目录

  • 什么是分治法?
  • 分析什么是全排列
  • 代码(c++)
  • java实现
  • 递归结构展示

什么是分治法?

先看分:将一个大问题分成若干个小问题,如果小问题还可以分,那就再分,直到小问题可以很轻易地解决

治:将小问题逐个解决,然后将解合起来,组成大问题的解。

下图是示意图:

在这里插入图片描述

分析什么是全排列

目的是对n不重复的字符{a1,a2,a3…an}进行全排列, 以n=4时为例,对{a,b,c,d}全排列可以写为

P(a,b,c,d)={a}P(b,c,d)+ {b}P(a,c,d) + {c}P(a,b,d) +{d}P(a,b,c);
即四个元素的全排列为下面四种情况相加:
(1)把第一个元素固定住,剩下的全排列 {a}P(b,c,d)
(2)把第二个元素固定住,剩下的全排列 {b}P(a,c,d)
(3)把第三个元素固定住,剩下的全排列 {c}P(a,b,d)
(4)把第四个元素固定住,剩下的全排列 {d}P(a,b,c)

也就是说,对n个元素的全排列是

a1和其余n-1个元素全排列的组合
+
a2和其余n-1个元素全排列的组合
+…+
an和其余n-1个元素全排列的组合

记作

P(a1,a2…an)={a1}P(a2…an)+ {a2}P(a1,a3,a4…an) + {a3}P(a1,a2,a4…an) +{an}P(a1…a(n-1));

同样的,对于上面的P(a2…an),我们同样可以分解为更小的组合:

P(a2…an)= {a2}P(a3…an)+ {a3}P(a2,a4…an) + {a4}P(a2,a3…an) +{an}P(a2…a(n-1));

如此往复一直分,直到什么情况为止呢?上面我们说了,分解子问题直到子问题可以很轻易地解决,那什么情况时全排列很容易解决呢?

我们发现当n=1时,P(a1)为{a1},即只有一个元素时,它的全排列就是它本身, 所以当要排列的元素个数为1时,我们可以直接得出结果,那就是前面元素加上它本身就是一种排列的情况。

如当n=2时,P(a1,a2)分解成{a1}P(a2)+ {a2}P(a1), 而P(a2)=a2, P(a1)=a1,所以结果为P(a1,a2)为{a1,a2}{a2,a1}

故对P(a,b,c,d)这个大问题,我们可以最终分解为:(下图列出了固定第一个元素的情况)

在这里插入图片描述

代码(c++)

#include "stdlib.h"
#include "stdio.h"

template<class Type>
inline  void swap(Type &a,Type &b,Type lt[])  {
   
  Type t = a; a = b;  b = t;
}

template<class Type>
inline  void printList(Type lt[]) {
   
  printf("==>%s\n\n",lt);
}

template<class Type>
void perm(Type list[], int k,int m)  {
   
  
  if(k==m) {
   
    swap(list[k],list[k],list);
    printList(list);
  }
  else {
   
    for(int i=k;i<=m;i++) {
   
      swap(list[k],list[i],list);
      perm(list,k+1,m);
      swap(list
  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值