分治法的设计思想:将一个难以直接解决的大问题,分解成一些规模较小的相同问题,以便各个击破,分而治之
直接或间接地调用自身的算法/函数称为递归算法/函数
用递归解决问题时,关键是确定递归体和递归出口
掌握用递归方法解决问题
n!
#include <iostream>
using namespace std;
int fn(int n){
int sum;
if(n==0){
sum=1;
}else{
sum=fn(n-1)*n;
}
return sum;
}
int main()
{
int n;
cin>>n;
cout<<fn(n)<<endl;
}
菲波那契数列
求菲波那契数列 (Fibonacci)数列的前40个数。这个数列有如下特点:第1、2两个数为1、1。从第3个数开始,该数是其前面两个数之和。
#include <iostream>
using namespace std;
int Fi(int n){
if(n<=2){
return 1;
}else{
return Fi(n-1)+Fi(n-2);
}
}
int main()
{
int fn[40];
for(int i=1;i<=40;i++){
fn[i]=Fi(i);
cout<<fn[i]<<endl;
}
}
猴子摘桃问题
猴子第一天摘下若干个桃子,当即吃了一半,好不过瘾,又多吃了一个。第二天早上又吃了剩下的桃子的一半,又多吃了一个。以后每天都吃了前一天剩下的一半零一个,到第10 天早上想再吃的时候,就剩下一个桃子。求第一天共摘多少个桃子。
#include <iostream>
using namespace std;
int taozi(int n){
int sum;
if(n==10){
return 1;
}else{
sum=(taozi(n+1)+1)*2;
return sum;
}
}
int main()
{
cout<<taozi(1)<<endl;
}
十进制转换为二进制
编写一个递归函数,将10进制转化成radix进制(输出二进制形式)
#include <iostream>
using namespace std;
void change(int a,int radix){
if(a!=0){
change(a/radix,radix);
cout<<a%radix;
}
}
int main()
{
int a,radix;
cin>>a>>radix;
change(a,radix);
cout<<endl;
return 0;
}
逆序(或正序)输出一个正数中的每一位数
逆序输出一个正数中的每一位数 例如,对于数12345,依次输出5 4 3 2 1
#include <iostream>
using namespace std;
int nixu(int n){
if(n!=0){
cout<<n%10;
nixu(n/10);
}else{
cout<<n;
}
}
int main()
{
int n;
cin>>n;
nixu(n);
return 0;
}
正序依次输出一个正数中的每一位数 例如,对于数12345,依次输出1 2 3 4 5
#include <iostream>
using namespace std;
int zhengxu(int n){
if(n!=0){
zhengxu(n/10);
cout<<n%10;
}else{
cout<<n;
}
}
int main()
{
int n;
cin>>n;
zhengxu(n);
return 0;
}
集合的全排列
设计一个递归算法生成n个元素{r1,r2,…,rn}的全排列(n!种)。
样例输入
3
样例输出
1 2 3 1 3 2 2 1 3 2 3 1 3 2 1 3 1 2
#include<iostream>
using namespace std;
void Perm(int list[], int k, int m){
if(k==m){
for(int i=0;i<=m;i++)
cout<<list[i]<<" ";
cout<<endl;
}
else {
for(int j=k;j<=m;j++){
swap(list[k],list[j]);
Perm(list,k+1,m);
swap(list[k],list[j]);
}
}
}
int main(){
int n;
cin>>n;
int a[5]={1,2,3,4,5};
Perm(a,0,n-1);
return 0;
}
递归求平方和函数(openjudge题目)
描述:
用递归函数,求
,n的值由主函数输入。
输入
输入n的值
输出
输出1-n的平方和
样例输入
4
样例输出
30
#include <iostream>
using namespace std;
int perm(int n){
if(n==1){
return 1;
}else{
return n*n+perm(n-1);
}
}
int main()
{
int n;
cin>>n;
cout<<perm(n)<<endl;
return 0;
}
分治:
分治法的设计思想:将一个难以直接解决的大问题,分解成一些规模较小的相同问题,以便各个击破,分而治之
分治法的基本思想是将一个规模为n的问题分解为k个规模较小的子问题,这些子问题互相独立且与原问题相同
子问题的解可以合并为该问题的解
掌握用分治法解决:
棋盘覆盖
81-84
找出这n个元素中第k小的元素(掌握线性时间选择法解决此问题)
元素选择问题:给定线性序集中n个元素和一个整数k,1≤k≤n,要求找出这n个元素中第k小的元素。
分析:
解决方法一:排序 时间复杂度O(nlogn)
解决方法二:优先队列 时间复杂度O(nlogn)
解决方法三:线性时间选择算法
模仿快速排序算法,
首先对输入数组进行划分,
然后对划分出的子数组之一进行递归处理。
快速排序的基本思想:
首先选第一个数作为分界数据, 将比它小的数据存储在它的左边,比它大的数据存储在它的右边,它存储在左、右两个子集之间。 这样左、右子集就是原问题分解后的独立子问题。
再用同样的方法,继续解决这些子问题,直到每个子集只有一个数据,就完成了全部数据的排序工作。
94-96
半数集问题
描述
给定一个自然数n,由n 开始可以依次产生半数集set(n)中的数如下。
(1) n∈set(n);
(2) 在n 的左边加上一个自然数,但该自然数不能超过最近添加的数的一半;
(3) 按此规则进行处理,直到不能再添加自然数为止。
例如,set(6)={6,16,26,126,36,136}。半数集set(6)中有6 个元素。
输入
输入一个自然数n
输出
半数集中数的个数
样例输入
6
样例输出
6
整数因子分解问题
大于1的正整数n可以分解为:
当n=12时,共有8种不同的分解式:
对于给定的正整数n,编程计算n共有多少种不同的分解式。
115