算法复习4:第3章 递归与分治策略

分治法的设计思想:将一个难以直接解决的大问题,分解成一些规模较小的相同问题,以便各个击破,分而治之

直接或间接地调用自身的算法/函数称为递归算法/函数

用递归解决问题时,关键是确定递归体和递归出口

掌握用递归方法解决问题

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值