关于全排的递归算法

注:该方法转自 李宁的极客世界

在做leetcode的时候遇到一道关于全排的题,于是去了解了有关的递归算法

思路:

1、首先看最后两个数4, 5。 它们的全排列为4 5和5 4, 即以4开头的5的全排列和以5开头的4的全排列。
由于一个数的全排列就是其本身,从而得到以上结果。
2、再看后三个数3, 4, 5。它们的全排列为3 4 5、3 5 4、 4 3 5、 4 5 3、 5 3 4、 5 4 3 六组数。
即以3开头的和4,5的全排列的组合、以4开头的和3,5的全排列的组合和以5开头的和3,4的全排列的组合.
从而可以推断,设一组数p = {r1, r2, r3, ... ,rn}, 全排列为perm(p),pn = p - {rn}。
因此perm(p) = r1perm(p1), r2perm(p2), r3perm(p3), ... , rnperm(pn)。当n = 1时perm(p} = r1。
为了更容易理解,将整组数中的所有的数分别与第一个数交换,这样就总是在处理后n-1个数的全排列。

#include<stdio.h>
int n=0;//  这里设置一个全局变量,用来记录有多少钟全排的情况
int main()
{
  void swap(int *a,int *b);
  void perm(int *list,int k,int m);
  nt list[]={1,2,3,4,5};
  perm(list,0,4);
  printf("total:%d\n",n);
  return 0;
}
void swap(int *a,int *b)
{
  int temp;
  temp=*a;
  *a=*b;
  *b=temp;
}
void perm(int *list,int k,int m)//  k和m都是数列的指引,一开始k是第一个即0,m是最后一个序号
{
  int i;
  if(k>m)//  结束的标志,即当k大于最后那个序列,就是说剩下最后一个数字的全排,就是它自己
  {
    for(i=0;i<=m;i++)
    printf("%d ",list[i]);
    printf("\n");
    n++;//  每到这里就以为着打出来了一种情况,所以n++

  }
  else
  {
    for(i=k;i<=m;i++)//  可以这样理解k是第一个序号,所以这个循环的意思就是遍历第一个到最后一个
    {
      swap(&list[i],&list[k]);//  意味从第一个到最后一个每一个都和第一个交换
      perm(list,k+1,m);//  开始递归
    }
  }
}

时间: 2024-10-22 13:02:22

关于全排的递归算法的相关文章

算法习题---字符串的全排序列

一:什么是全排列 排列:从n个元素中任取m个元素,并按照一定的顺序进行排列,称为排列: 全排列:当n==m时,称为全排列: 比如:集合{ 1,2,3}的全排列为: { 1 2 3} { 1 3 2 } { 2 1 3 } { 2 3 1 } { 3 2 1 } { 3 1 2 } 我们可以将这个排列问题画成图形表示,即排列枚举树,比如下图为{1,2,3}的排列枚举树,此树和我们这里介绍的算法完全一致: 二:全排列实现思路 (1)n个元素的全排列=(n-1个元素的全排列)+(另一个元素作为前缀):

输出1-n的全排(递归C++)

[问题描述] 输出1到n之间所有不重复的排列,即1到n的全排,要求所产生的任一数列不含有重复的数字. [代码展示] #include<iostream>using namespace std;int a[100],b[100];void quanpai(int index,int n){ //递归边界 if(index==n+1){ for(int i=1;i<=n;i++){ cout << a[i]; } cout << endl; return; } //向

递归算法及经典递归例子代码实现( 转自http://www.cnblogs.com/joinclear)

递归(recursion):程序调用自身的编程技巧. 递归满足2个条件: 1)有反复执行的过程(调用自身) 2)有跳出反复执行过程的条件(递归出口) 递归例子: (1)阶乘 n! = n * (n-1) * (n-2) * ...* 1(n>0) //阶乘 int recursive(int i) { int sum = 0; if (0 == i) return (1); else sum = i * recursive(i-1); return sum; } (2)河内塔问题 //河内塔 v

递归算法及经典递归例子代码实现

转自http://www.cnblogs.com/joinclear/archive/2013/02/06/2908247.html 递归(recursion):程序调用自身的编程技巧. 递归满足2个条件: 1)有反复执行的过程(调用自身) 2)有跳出反复执行过程的条件(递归出口) 递归例子: (1)阶乘 n! = n * (n-1) * (n-2) * ...* 1(n>0) //阶乘 int recursive(int i) { int sum = 0; if (0 == i) return

[经典算法] 排列组合-全排序

题目说明: 将一组数字.字母或符号进行排列,以得到不同的组合顺序,例如1 2 3这三个数的全排列有:1 2 3.1 3 2.2 1 3.2 3 1.3 1 2.3 2 1. 题目解析: 设一组数p = {r1, r2, r3, - ,rn}, 全排列为perm(p),pn = p – {rn}. 则perm(p) = r1perm(p1), r2perm(p2), r3perm(p3), - , rnperm(pn).当n = 1时perm(p} = r1. 如:求{1, 2, 3, 4, 5}

递归深度实战

先不说理论,先来个简单的递归小例子感受一下: 字符串的反转: #include <stdio.h> //递归字符串反转 void reverse(char* s) { if( (s != NULL) && (*s != '\0') ) { reverse(s + 1); printf("%c", *s); } } int main(int argc, char *argv[]) { reverse("12345"); printf(&qu

递归解决全排列生成算法

排列:从n个元素中任取m个元素,并按照一定的顺序进行排列,称为排列: 全排列:当n==m时,称为全排列: 比如:集合{ 1,2,3}的全排列为: { 1 2 3} { 1 3 2 } { 2 1 3 } { 2 3 1 } { 3 2 1 } { 3 1 2 } 方法一: 我们可以将这个排列问题画成图形表示,即排列枚举树,比如下图为{1,2,3}的排列枚举树,此树和我们这里介绍的算法完全一致: 算法思路: (1)n个元素的全排列=(n-1个元素的全排列)+(另一个元素作为前缀): (2)出口:如

算法设计-全排列递归

排列:从n个元素中任取m个元素,并按照一定的顺序进行排列,称为排列: 全排列:当n==m时,称为全排列: 比如:集合{ 1,2,3}的全排列为: { 1 2 3} { 1 3 2 } { 2 1 3 } { 2 3 1 } { 3 2 1 } { 3 1 2 } 我们可以将这个排列问题画成图形表示,即排列枚举树,比如下图为{1,2,3}的排列枚举树,此树和我们这里介绍的算法完全一致: 算法思路: (1)n个元素的全排列=(n-1个元素的全排列)+(另一个元素作为前缀): (2)出口:如果只有一个

“奇技淫巧” 话递归

“To Iterate is Human, to Recurs,Divine.” ---L. Peter Deutsch “迭代是人,递归是神” 第一次见有人这样说,让我受伤的心得到些许安慰...... 最近在琢磨算法,又见递归! 这是个绕不过去的坎! 当初,上大学时似懂非懂自欺欺人的蒙混过关,再次引证了那句名言:“出来混,迟早都是要还的......”.好吧,那就直面它!于是搜遍海内外,加上日思夜想,被这“奇技淫巧”折魔得真掉了不少头发(主要是8皇后问题~). 大神王垠在谈程序语言最精华的原理时