分治法应用——全排列

目录

  • 什么是分治法?

  • 分析什么是全排列

  • 代码(c++)

  • java实现

  • 递归结构展示

什么是分治法?

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

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

下图是示意图:

image

分析什么是全排列

目的是对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)这个大问题,我们可以最终分解为:(下图列出了固定第一个元素的情况)

image

代码(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[k],list[i],list);
    }
  }
}

int main(int argc, char* argv[])  {
  char ll[] = "abcd";
  perm(ll,0,3);

  system("pause");
  return 0;
}

java实现

摘自zyoung贡献

public class Demo {
    public void Perm(char list[], int k, int m) {
        if (k == m) {
            for (int i = 0; i <= m; i++)
                System.out.print(list[i]);
            System.out.println();
        } else {
            for (int i = k; i <= m; i++) {
                // 从固定的数后第一个依次交换
                Swap(list, k, i);
                Perm(list, k + 1, m);
                // 这组递归完成之后需要交换回来
                Swap(list, k, i);
            }
        }
        
    }
    public void Swap(char[] list, int i, int j) {
        char t = list[i];
        list[i] = list[j];
        list[j] = t;
    }
    public static void main(String[] args) {
        Demo d = new Demo();
        char[] arr = {a,b,c,d};
        d.Perm(arr, 0, 3);
    }
}

递归结构展示

输入:Perm(list, 0, 3 ) 
=====i=k=0,i<=3(第一个为a)
    Swap(0,0)abcd
    Perm(list,1,3)
        =========i=k=1,i<=3
        Swap(list , 1, 1)abcd
        Perm(list, 2, 3)
            ======i=k=2, i<=3
            Swap(2,2)abcd
            Perm(list, 3,3)
                Print(list)abcd
            Swap(list,2,2)
            =====i=i+1,i=3
            Swap(2,3)abdc
            Perm(list, 3,3)
                Print(list)abdc
            Swap(list,2,3)abcd
            ======out
        Swap(list,1,1)abcd


        ========i=i+1, i=2<3,k=1
        Swap(list , 1, 2)acbd
        Perm(list, 2, 3)
            ======i=k=2, i<=3
            Swap(2,2)acbd
            Perm(list, 3,3)
                Print(list)acbd
            Swap(list,2,2)acbd
            =====i=i+1,i=3
            Swap(list,2,3)acdb
            Perm(list, 3,3)
                Print(list)acdb
            Swap(list,2,3)acbd
            ======out
        Swap(list,1,2)abcd



        ========i=i+1, i=3,k=1
        Swap(list , 1, 3)adcb
        Perm(list, 2, 3)
            ======i=k=2, i<=3
            Swap(2,2)adcb
            Perm(list, 3,3)
                Print(list)adcb
            Swap(list,2,2)adcb
            =====i=i+1,i=3
            Swap(list,2,3)adbc
            Perm(list, 3,3)
                Print(list)adbc
            Swap(list,2,3)adcb
            ======out
        Swap(list,1,3)abcd
        =========out
    Swap(0,0)abcd

=====i=i+1,i=1,i<=3,k=0(第一个为b)
    Swap(0,1)bacd
    Perm(list,1,3)
        =========i=k=1,i<=3
        Swap(list , 1, 1)bacd
        Perm(list, 2, 3)
            ======i=k=2, i<=3
            Swap(2,2)bacd
            Perm(list, 3,3)
                Print(list)bacd
            Swap(list,2,2)
            =====i=i+1,i=3
            Swap(2,3)badc
            Perm(list, 3,3)
                Print(list)badc
            Swap(list,2,3)bacd
            ======out
        Swap(list,1,1)bacd


        ========i=i+1, i=2<3,k=1
        以此类推

out

==>abcd
==>abdc
==>acbd
==>acdb
==>adcb
==>adbc

==>bacd
==>badc
==>bcad
==>bcda
==>bdca
==>bdac

==>cbad
==>cbda
==>cabd
==>cadb
==>cdab
==>cdba

==>dbca
==>dbac
==>dcba
==>dcab
==>dacb
==>dabc
该文章同步发表于csdn

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容

  • 在C语言中,五种基本数据类型存储空间长度的排列顺序是: A)char B)char=int<=float C)ch...
    夏天再来阅读 3,320评论 0 2
  • 1. 关于诊断X线机准直器的作用,错误的是()。 (6.0 分) A. 显示照射野 B. 显示中心线 C. 屏蔽多...
    我们村我最帅阅读 10,255评论 0 5
  • 专业考题类型管理运行工作负责人一般作业考题内容选项A选项B选项C选项D选项E选项F正确答案 变电单选GYSZ本规程...
    小白兔去钓鱼阅读 8,970评论 0 13
  • 总是小心翼翼的活着,所以看到别人那么坦然的生活才会羡慕吧。 小的时候,担心没有朋友,于是不论对方说的对的错的,如果...
    冰茯苓阅读 281评论 0 0
  • (一) 凌晨两点零六,窗外鹅毛大雪,病房里的日光灯寂静地亮着,惨白的灯光照亮病房的边边角角,照亮了爸爸病床边的真空...
    水墨丹青_阅读 294评论 4 3