第二章 递归与分治策略(排列的字典序问题)
来源:互联网 发布:印尼屠侨真相知乎 编辑:程序博客网 时间:2024/06/03 23:27
一. 递归
1.概念
直接或间接地调用自身的算法。用函数自身给出定义的函数称为递归函数。
2.说明
(1)每个递归函数都必须有非递归定义的初始值,否则,递归函数就无法计算。
(2)递归式的主要表达式是用较小自变量的函数值来表示较大自变量的函数值。
3°.一种特殊的递归函数:双递归函数(一个函数及他的一个变量由函数自身定义)
二. 分治法
1.基本思想
将一个规模为n的问题分解为k个规模较小的子问题,这些子问题相互独立且与原问题相同。递归地解决这些子问题,然后将各子问题的解合并得到原问题的解。
2.算法复杂度计算
用分治法将一个规模为n的问题分为k个规模为n/m的子问题解。
将递归式展开反复带入求解的:
还有一个常见的递归式(不是分治法解决时的复杂度表达式):
问题:排列的字典序问题
问题描述:
n个元素{1,2,, n }有n!个不同的排列。将这n!个排列按字典序排列,并编号为0,1,…,
n!-1。每个排列的编号为其字典序值。例如,当n=3时,6 个不同排列的字典序值如下:
算法设计:
给定n以及n个元素{1,2,, n }的一个排列,计算出这个排列的字典序值,以及按字典
序排列的下一个排列。
数据输入:
输出元素个数n。接下来的1 行是n个元素
{1,2,, n }的一个排列。
结果输出:
将计算出的排列的字典序值和按字典序排列的下一个排列输出。第一行是字典序值,第2行是按字典序排列的下一个排列。
Sample Input
8
2 6 4 5 8 1 7 3
Sample Output
8227
2 6 4 5 8 3 1 7
分析:其实这题并没有用上前面说的递归和分治法,分析一下找找规律就可以解决的。设这排列的第一个数是k,则以1,2,…,k-1开头的所有排列都在目标排列之前,共有(k-1)*(n-1)!个;以此类推再分析第二个(注意要排除前面已经出现数的排列)…..到第n-1个只有一种排列或没有;然后求和即可得到字典序值。
C++代码:(输入输出分别在input.txt和output.txt文件中)
#include<iostream>#include<fstream>using namespace std;//the factorials of nint factorial(int n){ int answer=1; for (int i = 1; i <= n; i++) answer *= i; return answer;}int main(){ //initiate file ofstream createFile("input.txt"); createFile << "8" << endl; createFile << "26458173" << endl; createFile.close(); ifstream ReadFile("input.txt"); ofstream WriteFile("output.txt"); //read data from input.txt char num; ReadFile.get(num); int nums = (int)num - 48; char line; ReadFile.get(line); char *chara = new char[nums]; for (int i = 0; i < nums;i++) ReadFile.get(chara[i]); int *a = new int[nums]; for (int i = 0; i < nums; i++) a[i]=(int)chara[i]-48; //find its order: int cnt=0; for (int i = 0; i < nums; i++){ for (int j = 1; j < a[i]; j++){ bool judge = 1; for (int k = 0; k < i; k++) if (j == a[k]) judge = 0; if (judge) cnt += factorial(nums - i - 1); } } cout << cnt << endl; WriteFile << cnt << endl; //find the next one: for (int i = nums-2; i >= 0;i--) if (a[i]>a[nums - 1]){ int temp = a[i]; for (int j = i + 1; j <= nums - 1; j++) a[j-1] = a[j]; a[nums-1] = temp; } else{ for (int j = nums - 1; j >= i;j--) if (a[i] >= a[j]){ int temp = a[i]; a[i] = a[j + 1]; a[j + 1] = temp; break; } break; } for (int i = 0; i < nums; i++){ cout << a[i]; WriteFile << a[i]; } system("pause");}
- 第二章 递归与分治策略(排列的字典序问题)
- 第二章 递归与分治策略
- 第二章 递归与分治策略
- 递归与分治——字典序排列
- 字典序问题-递归与分治
- 算法学习(1)分治策略(递归,排列问题)
- 递归和分治策略之排列问题
- 全排列的递归实现--分治策略
- 分治策略--排列问题
- 分治与递归(一)----全排列问题
- 分治与递归法:全排列问题
- 递归与分治——排列问题
- 《算法之美》の递归与分治策略の全排列问题
- Java语言描述:递归与分治策略之全排列问题
- 递归与分治策略-2.1.4全排列
- 分治与递归策略_hanio塔问题
- 全排列问题问题的两种算法--递归与字典序
- 递归与分治策略
- 基于jQuery实现的点击编辑按钮时传递参数到弹出层div
- sql语句删除重复行
- Hihocoder #1284 : 机会渺茫
- Linux ext2, ext3, ext4 文件系统解读[2]
- 编写高效且优雅的 Python 代码
- 第二章 递归与分治策略(排列的字典序问题)
- Oracle笔记1
- 神经网络sim实现原理,及原理坑的方法。
- centOS6.5安装sphinx扩展
- 面向对象—静态代码块+构造代码块+局部代码块
- 易错的api和坑
- 9273:PKU2506Tiling
- Oracle的sqlnet.ora文件配置
- 网易云课堂 Linux内核分析期末总结