全排列的递归算法C++(带截图)
- 格式:doc
- 大小:213.50 KB
- 文档页数:2
全排列递归算法概述及举例说明1. 引言1.1 概述在计算机科学中,全排列递归算法是一种常见且重要的算法。
它能够通过递归的方式生成给定元素集合的所有可能排列组合。
全排列递归算法的实现原理相对简单,但其应用领域十分广泛,并在许多其他算法中扮演着关键角色。
1.2 文章结构本文将首先介绍全排列递归算法的概述,包括其定义、特点和应用场景等。
随后,我们将深入探讨该算法的实现原理,并对其优缺点进行详尽分析。
接下来,我们会通过三个具体的举例说明来展示全排列递归算法的具体运用情况。
在最后部分,我们将探究该算法在其他领域中的应用以及进一步扩展与改进思路。
1.3 目的本文旨在提供一个清晰而全面的介绍全排列递归算法及其应用示例。
通过阅读本文,读者将能够了解该算法的基本原理、实现方法和优缺点,并对其在不同场景下的具体应用有更深入、更具体的认识。
此外,本文还将探讨该算法的拓展和改进思路,为读者提供继续研究和应用的思路。
2. 全排列递归算法概述2.1 什么是全排列递归算法全排列递归算法是一种用于确定给定元素集合所有可能排列方式的算法。
它通过递归的方式将原始集合分解成更小的子问题,并且在每个步骤中交换不同位置上的元素来生成新的排列。
这个过程会一直持续到达到基本情况,也就是无法再进一步交换元素位置为止。
2.2 实现原理全排列递归算法可以通过以下方法实现:1) 确定基本情况:当待排序集合只包含一个元素时,即达到了基本情况。
此时,我们可以认为该集合已经被排列好了。
2) 对于超过一个元素的集合,选择其中一个元素作为固定元素,并将其与其他每个位置上的元素进行交换。
这样,我们就得到了以不同元素开头的一系列子问题。
3) 对于每个子问题,重复步骤2中的操作,对其余部分进行递归地全排列。
4) 在重复进行步骤2和3后,我们可以得到最终的全排列结果。
2.3 优缺点分析全排列递归算法具有以下优点:- 算法逻辑简单易懂,易于实现和理解。
- 能够生成给定元素集合的所有可能排列方式。
字符串全排列的输出(递归解法)题⽬描述输⼊⼀个字符串,按字典序打印出该字符串中字符的所有排列。
例如输⼊字符串abc,则按字典序打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
输⼊描述:输⼊⼀个字符串,长度不超过9(可能有字符重复),字符只包括⼤⼩写字母。
⽰例1输⼊"ab"返回值["ab","ba"]题⽬如上,其实这是⼀道⽔题,但是好像做题的时候思路不对上就容易⾛⽕⼊魔,原本打算⽤dp做出来。
奈何不太熟不知道从何dp,于是看了下官⽅题解,把这个思路记录下来。
在原始字符串上进⾏操作的话,就不⽤担⼼漏了字符和字符重复什么的问题,⽤set暂存结果可以过滤多余的字符串结果。
思路⼤致这样,对⽬标string每两个字符进⾏⼀次换位,中间递归其他字符的交换,同时在得到⼀次结果之后回溯,因为换位之后其他分⽀的结果需要原来的字符串嘛,这样才能保证结果⽐较全⾯,接下来是附带注解的代码。
class Solution {public:vector<string> Permutation(string str) {//递归解法if(str.empty())return {};//字符串为空直接返回空结果set<string> st;//字典可以过滤多余结果change(0,str,st);return vector<string>({st.begin(),st.end()});//类型转换}void change(int position,string s,set<string> &st){for(int i=position;i<s.length();i++){//这⾥i=position 是防⽌漏了原始字符串的结果swap(s[position],s[i]);change(position+1,s,st);//递归其他部分的字符串st.insert(s);//结果记录swap(s[position], s[i]);//回溯}}};⼜⽔了⼀份题解。
⽣成n个数的全排列【递归、回溯】下⾯讨论的是n个互不相同的数形成的不同排列的个数。
毕竟,假如n个数当中有相同的数,那n!种排列当中肯定会有⼀些排列是重复的,这样就是⼀个不⼀样的问题了。
/*=====================================数的全排列问题。
将n个数字1,2,…n的所有排列枚举出来。
2 3 12 1 33 1 23 2 1思路:递归函数定义如下:void fun(int a[],int flag[],int i,int ans[]);//原始数据存放于a[]。
flag[]的每⼀个元素标记a[]对应位置处的元素是否已经被选⽤。
//i表⽰当前对某排列⽽⾔,正在寻找到第i个数据。
//ans[]是存放每⼀个排列的地⽅。
每当放够n个元素到ans则开始打印该数组。
程序中先把原始数据读⼊到数组a[]。
flag[]数组元素全部置0.⽣成⼀个排列的过程可以这样认为:每次递归都扫描flag[],寻找⼀个flag[i]==0然后把a[i]选到排列当中。
(也即放到ans[i]当中。
选a[i]后要把flag[i]置1.)这样就确定了当前排列的第i个元素。
然后递归进⼊下⼀层确定第i+1个数。
以此类推,逐层递归直⾄i==n-1(因为i从0开始,所以是i==n-1)就认为已经得到了⼀个完整的排列。
这个时候可以把ans数组输出了。
输出后可以开始回溯了。
每次回溯都要把flag[i]置0以便还原现场。
(相当于ans[i]不选a[i]了。
)置0后继续循环枚举当前位置的其他可能取值。
======================================*/下⾯是我⾃⼰按照⾃⼰的理解做的,其实有点浪费空间了:1 #include<stdio.h>2int n,count;//n表⽰参与排列的数据的个数,count表⽰不同排列的个数3void fun(int a[],int flag[],int i,int ans[]);4//原始数据存放于a[]。
/index.php全排列是将一组数按一定顺序进行排列,如果这组数有n个,那么全排列数为n!个。
现以{1, 2, 3, 4, 5}为例说明如何编写全排列的递归算法。
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 53、 5 34、 5 43 六组数。
即以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;void swap(int *a, int *b){int m;m = *a;*a = *b;*b = m;}void perm(int list[], int k, int m){int i;if(k > m){for(i = 0; i <= m; i++)printf("%d ", list[i]);printf("\n");n++;}else{for(i = k; i <= m; i++){swap(&list[k], &list[i]);perm(list, k + 1, m);swap(&list[k], &list[i]);}}}int main(){int list[] = {1, 2, 3, 4, 5};perm(list, 0, 4);printf("total:%d\n", n);return 0;}谁有更高效的递归和非递归算法,请回贴。
全排列是指一组数的所有排列组合。
要求出n 个数字的全排列,可以使用递归的方法。
假设我们要求出3 个数字1、2、3 的全排列,可以这样做:
1.以1 开头的排列:
• 1 开头,2 和3 交换位置:1 2 3
• 1 开头,3 和2 交换位置:1 3 2
2.以2 开头的排列:
• 2 开头,1 和3 交换位置:2 1 3
• 2 开头,3 和1 交换位置:2 3 1
3.以3 开头的排列:
• 3 开头,1 和2 交换位置:3 1 2
• 3 开头,2 和1 交换位置:3 2 1
这样,就能得到3 个数字的全排列:1 2 3、1 3 2、2 1 3、2 3 1、3 1 2、3 2 1。
要求出n 个数字的全排列,可以使用类似的方法。
例如,要求出4 个数字的全排列,可以使用类似的方法,只需要以1、2、3、4 开头,然后对剩下的数字进行全排列即可。
这样的算法是暴力枚举法,时间复杂度为O(n!),在n 较大时可能会很慢。
有更快的算法可以用来求出n 个数字的全排列,例如Heap 算法。
全排列递归问题全排列问题是典型的递归问题。
该问题的解决思路为:对于一个长度为n的序列,将其分成两部分,第一部分为第一个元素,第二部分为剩下的元素,那么全排列就等于将第一个元素与剩下的元素交换位置,并对剩下的元素再进行全排列。
以下是一份Python实现的代码:```pythondef permutation(nums, start, end):if start == end:print(nums) # 打印结果else:for i in range(start, end + 1):nums[i], nums[start] = nums[start], nums[i] # 交换元素顺序permutation(nums, start + 1, end) # 对剩下的元素进行全排列nums[i], nums[start] = nums[start], nums[i] # 恢复原来的排列nums = [1, 2, 3]n = len(nums)permutation(nums, 0, n - 1)```在该代码中,`nums`表示待排序的列表,`start`表示列表的起始位置,`end`表示列表的终止位置。
在主函数中,首先定义了列表`nums`和它的长度`n`。
然后调用`permutation`函数进行递归排序。
`start`初始值为0,`end`初始值为`n-1`。
在`permutation`函数中,如果`start`和`end`的值相等,说明已经排列好了一个全排列,直接输出结果。
否则就从区间[ `start`, `end`]中选取一个数字进行交换,并递归进行全排列。
递归完成后,将交换的数字恢复其原来的位置。
最终,程序将输出所有可能的全排列。
全排列C++编程全排列的生成算法全排列的生成算法就是对于给定的字符集,用有效的方法将所有可能的全排列无重复无遗漏地枚举出来。
任何n个字符集的排列都可以与1~n的n个数字的排列一一对应,因此在此就以n个数字的排列为例说明排列的生成法。
n个字符的全体排列之间存在一个确定的线性顺序关系。
所有的排列中除最后一个排列外,都有一个后继;除第一个排列外,都有一个前驱。
每个排列的后继都可以从它的前驱经过最少的变化而得到,全排列的生成算法就是从第一个排列开始逐个生成所有的排列的方法。
全排列的生成法通常有以下几种:字典序法递增进位数制法递减进位数制法邻位交换法递归类算法1.字典序法字典序法中,对于数字1、2、3......n的排列,不同排列的先后关系是从左到右逐个比较对应的数字的先后来决定的。
例如对于5个数字的排列12354和12345,排列12345在前,排列12354在后。
按照这样的规定,5个数字的所有的排列中最前面的是12345,最后面的是54321。
字典序算法如下:设P是1~n的一个全排列:p=p1p2......pn=p1p2......pj-1pjpj+1......pk-1pkpk+1......pn 1)从排列的右端开始,找出第一个比右边数字小的数字的序号j(j从左端开始计算),即j=max{i|pi<pi+1}2)在pj的右边的数字中,找出所有比pj大的数中最小的数字pk,即k=max{i|pi>pj}(右边的数从右至左是递增的,因此k是所有大于pj的数字中序号最大者)3)对换pi,pk4)再将pj+1......pk-1pkpk+1pn倒转得到排列p''=p1p2.....pj-1pjpn.....pk+1pkpk-1.....pj+1,这就是排列p的下一个下一个排列。
例如839647521是数字1~9的一个排列。
从它生成下一个排列的步骤如下:自右至左找出排列中第一个比右边数字小的数字4 839647521在该数字后的数字中找出比4大的数中最小的一个5 839647521将5与4交换839657421将7421倒转839651247所以839647521的下一个排列是839651247。
c++ 递归算法经典实例详解递归算法是一种通过重复调用自身来解决问题的编程方法。
在C++中,递归可以用于解决各种问题,例如排序、搜索、树遍历等等。
下面是一个经典的递归算法实例:斐波那契数列。
问题描述:给定两个整数n和m,求第n个斐波那契数列的值fn,其中fn=mfn-1+fn-2 (n>1),fn=m (n=1),fn=0 (n=0)。
以下是用C++实现的递归算法:c#include <iostream>using namespace std;int fibonacci(int n, int m) {if (n == 0) {return 0;} else if (n == 1) {return m;} else {return fibonacci(n-1, fibonacci(n-2, m));}}int main() {int n = 10, m = 2;cout << "The " << n << "th Fibonacci number is: " << fibonacci(n, m) << endl;return 0;}解释:在上面的代码中,我们定义了一个名为fibonacci的函数,该函数采用递归方法来计算第n个斐波那契数列的值。
如果n等于0,则返回0;如果n等于1,则返回m;否则,我们可以通过递归调用fibonacci函数来计算fn-1和fn-2的值,并将它们相加得到fn的值。
在main 函数中,我们定义了n和m的值,并调用fibonacci函数来计算第n个斐波那契数列的值,并输出结果。
需要注意的是,递归算法虽然简单易懂,但是可能会导致栈溢出等问题。
因此,在使用递归算法时需要谨慎考虑递归深度等因素。
虽说这是个蛮基础的东西但这个鸟东西困扰了我十年了今天终于解决了~惭愧啊实际上问题并不在于全排列问题本身而是在于basic中的goto当年basic中的方法是搜索回溯十来行的代码里面三个goto搞的人团团转最后终于彻底失去了继续参加竞赛的兴趣和动力然后一晃就是十年今天正在看programming in lua又见这个鸟问题是用lua实现的递归算法看了英文原版的书如醍醐灌顶豁然开朗原来这么简单!打印数组a{1,2,...,n}的全排列递归思想:取出数组中第一个元素放到最后,即a[1]与a[n]交换,然后递归求a[n-1]的全排列1)如果数组只有一个元素n=1,a={1} 则全排列就是{1}2)如果数组有两个元素n=2,a={1,2} 则全排列是{2,1}--a[1]与a[2]交换。
交换后求a[2-1]={2}的全排列,归结到1){1,2}--a[2]与a[2]交换。
交换后求a[2-1]={1}的全排列,归结到1)3)如果数组有三个元素n=3,a={1,2,3} 则全排列是{{2,3},1}--a[1]与a[3]交换。
后求a[3-1]={2,3}的全排列,归结到2){{1,3},2)--a[2]与a[3]交换。
后求a[3-1]={1,3}的全排列,归结到2){{1,2},3)--a[3]与a[3]交换。
后求a[3-1]={1,2}的全排列,归结到2)...以此类推。
马上用C代码实现,成功!#include <stdio.h>int g_count = 1;int g_n = 0;void print_result(int *a){int i = 0;printf("count %d:", g_count++);for (i=0; i<g_n; i++){printf(" %d", a[i]);}printf("\n");return;}#define swap(a, b)\{\int tmp = a;\a = b;\b = tmp;\}void p(int *a, int size){if (size == 1)print_result(a);else{int i, tmp = 0;for (i=0; i<size; i++){swap(a[i], a[size-1]); p(a, size-1);swap(a[i], a[size-1]); }}return;}void main(void){int array[] = {1, 2, 3, 4};g_n = sizeof(array) / sizeof(int);p(array, g_n);return;}。