003-生成排列-归纳法-《算法设计技巧与分析》M.H.A学习笔记
2016-06-27 16:27
295 查看
我们来生成1,2,3,...,n的全排列,这里只说两种与归纳法有关的算法,其他的算法还有几个,也有不是递归的算法,这里先不多讲。
首先吐槽一下这两个伪代码看书看了很久才理解,原因就是他们放在归纳法这一章里面,还配了一堆让人更加混乱的文字解释。其实递归就是递归,递归总是很好理解的,跟着代码运行一遍跑到停止的条件(dfs)或是每一层(深度)每一层(深度)去模拟(bfs),再把图画出来,过程总是很明朗的,递归真的只是算法里最容易理解的东西。
看下书中的伪代码,理解了很久才看懂,其实只要知道其中的交换实质上只是为了给各个位置安排不同的数这一点,代码就明朗了。
然后下面的知识来自高考数学倒数第二题第一小题的求数列表达式:
下面用到积分,我的噩梦。
最后我们得到:
这里贴图贴得有点啰嗦,但这个思路是很多递归算法计算复杂度的思路。以后类似的计算就不贴了,可以自己举一反三。
最后,贴一下找到的一个C++代码:
plain copy
#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, 5);
printf("total:%d\n", n);
return 0;
}
首先吐槽一下这两个伪代码看书看了很久才理解,原因就是他们放在归纳法这一章里面,还配了一堆让人更加混乱的文字解释。其实递归就是递归,递归总是很好理解的,跟着代码运行一遍跑到停止的条件(dfs)或是每一层(深度)每一层(深度)去模拟(bfs),再把图画出来,过程总是很明朗的,递归真的只是算法里最容易理解的东西。
算法一:
基本思想:
假设已经生成了2,3,...,n的全排列,再在其前面加上1,类似的,生成1,3,...,n的全排列,再在前面加上2,以此类推。然后递归的,依次缩小已经生成的全排列的规模,指导只剩下一个数。下面的伪代码用交换的方法来为每个位置放置不同数字,其实这和从无到有构造一棵多叉树是没有区别的。搜索的路径都是下面这个样子。看下书中的伪代码,理解了很久才看懂,其实只要知道其中的交换实质上只是为了给各个位置安排不同的数这一点,代码就明朗了。
伪代码:
算法分析:
对于复杂度,我们有下面这个递推式:然后下面的知识来自高考数学倒数第二题第一小题的求数列表达式:
下面用到积分,我的噩梦。
最后我们得到:
这里贴图贴得有点啰嗦,但这个思路是很多递归算法计算复杂度的思路。以后类似的计算就不贴了,可以自己举一反三。
最后,贴一下找到的一个C++代码:
C++代码:
[cpp] viewplain copy
#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, 5);
printf("total:%d\n", n);
return 0;
}
算法二:
另一个Θ(nn!)的算法,其实和前面的算法并没有什么本质的区别。不同之处在于前面的算法是每次给一个位置安排一个数,而这里是每次给一个数安排一个位置。一点都不乱,嗯。伪代码:
相关文章推荐
- 书评:《算法之美( Algorithms to Live By )》
- 动易2006序列号破解算法公布
- C#递归算法之分而治之策略
- Ruby实现的矩阵连乘算法
- C#插入法排序算法实例分析
- C#算法之大牛生小牛的问题高效解决方法
- C#算法函数:获取一个字符串中的最大长度的数字
- 超大数据量存储常用数据库分表分库算法总结
- C#数据结构与算法揭秘二
- C#冒泡法排序算法实例分析
- 算法练习之从String.indexOf的模拟实现开始
- C#算法之关于大牛生小牛的问题
- C#实现的算24点游戏算法实例分析
- 经典排序算法之冒泡排序(Bubble sort)代码
- c语言实现的带通配符匹配算法
- 浅析STL中的常用算法
- 算法之排列算法与组合算法详解
- C++实现一维向量旋转算法
- Ruby实现的合并排序算法
- C#折半插入排序算法实现方法