第1章递归函数

2024-03-27 22:52
文章标签 递归函数

本文主要是介绍第1章递归函数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

第1章 递归函数的设计技巧

  • 数学归纳法

  • 递归函数设计三个重要部分

  • 递归求阶乘

数学(结构)归纳法
  1. 验证P(1)成立
  2. 证明如果P(k)成立,那么P(k+1)成立
  3. 联合Step1和Step2,证明P(1)->P(n)成立
递归函数
  1. 给递归函数一个明确的语义
  2. 实现边界条件时的程序逻辑(p(1))
  3. 假设递归函数调用返回结果是正确的,实现本层函数逻辑 ( p(k) )
//递归 n的阶乘
//1.acm_1_1_diGui_test6代表n的阶乘的结果
int acm_1_1_diGui_test(int n){if(n==1)return 1; //边界条件 n==1return acm_1_1_diGui_test(n-1)*n; //利用f(n-1)结果计算f(n)的值
}//猴子吃桃
//猴子吃n天桃子的数量
int acm_1_1_diGui_test2(int n){if(n==1)return 1;return (acm_1_1_diGui_test2(n-1)+1)*2;
}

例题

一个小球,掉落到一连串弹簧板上,每个弹簧板回弹a[i]个距离,问小球弹 几次会弹出弹簧板串

5

2 2 3 1 2

2表示会弹2个距离,所以是2+3==5 ,

到三会弹3个距离,5+3=8>5

所以弹了两次

  1. f(i)小球从i位置开始被弹出的次数
  2. i>=n 时结束
  3. f(i)=f(i+a[i])+1
i=0
res=0
n=int(input())
ns=list(map(int,input().split(" ")))
while(i<n):i+=ns[i]res+=1
print(res)

例题:

输出n的指数型枚举

in:

3

out:

1
1 2
1 2 3
1 3
2
2 3
3

分析:

f(i,j,n) ,i表示第i个位置,j表示最小,n表示最大

边界条件是j>n ,最小值比最大值大的时候

  1. 如何按照字典序输出?

从小到大进行枚举每个位置的数字就是字典序

  1. 如何保证每个位置数字都大于前面的数字?

传入一个量,标记当前位置的最小值

每个枚举的过程都传入另一个数字,这个数字他标记了当前位置最小可以选取的数字

  1. 如何输出?
int arr[10]; 
def fn(int i,int j,int n){if (j>n) return;for(int k=j;k<=n;k++){ //j代表最小值,只能输出从j到narr[i]=k;//i代表第几个位置, 其中arr[j]一定比arr[i]前面的都大print_one_result(i); //输出前i个,i表示到了第几个位置fn(i+1,j+1,n); }
}//输出从arr数组从0到n的元素
void print_one_result(int n){cout << "n" << n << endl;for(int i=0;i<=n;i++){if(i){cout << " ";}cout << arr[i];}cout << endl;
}
int n;
cin >> n; //对n进行指数枚举
acm_1_1_diGui_fn3(0,1,n);
f(n)的n==ikarrji
01110
121 221
231 2 332
131 321
02210
132 331
03310

结论:

i==n为输出的个数

k为最后一个元素值

结束条件:j用来限定输出最小值,j永远不超过3

因为是递归,所以看k的值可以看出来属于哪一层递归

1

​ 2 3

​ 3

2

​ 3

3

arr=[0]*10
def print_one_result(n):for i in range(0,n+1):if i:print(" ",end="")print(arr[i],end="")print()def fn3(i,j,n):if(j>n): return;for k in range(j,n+1):arr[i]=kprint_one_result(i)fn3(i+1,k+1,n);def fn3_Test():n=int(input())fn3(0,1,n)
fn3_Test()

例题:

递归实现组合型枚举

in:

3 2

out:

1 2

1 3

2 3

  1. 如何按照字典序输出所有方案?

枚举每个位置直接从小到大

  1. 当前位置可以选取的最小值是什么–设置变量

  2. 怎么输出?

if i ==m,就

f(i,j,n) 第i个位置的最小值j和最大值n

边界是是否有足够多数

void acm_1_1_print_one_result5(int n){for(int i=0;i<n;i++){if (i) cout << " ";cout << arr[i];}cout << endl;
}
void acm_1_1_diGui_fn5(int i,int j,int n,int m){if(i==m){acm_1_1_print_one_result5(m);return;}for(int k=j;k<=n && m-i-1<=n-k;k++){arr[i]=k;acm_1_1_diGui_fn5(i+1,k+1,n,m);}return;
}
void acm_1_1_diGui_test5(){int n,m; //n代表输入是几 ,m代表每次输出几个数cin >> n >> m;acm_1_1_diGui_fn5(0,1,n,m);//0 代表第几个位置//1 代表当前位置最小可以选择的值//n 代表当前位置最大可以选择的值//m 最多枚举多少倍
}

例题:

按照字典序列,输出所有1到n这n个整数的所有方案

  1. 递归函数长什么样?----f(i,n)
  2. i==n的时候-》返回输出
//按照字典序输出所有1到n这n个整数的方案
int arr6[10],vis6[10]={0};
void acm_1_1_print_one_result6(int n){for(int i=0;i<n;i++){if(i) cout << " ";cout << arr6[i];}cout << endl;return;
}
void acm_1_1_diGui_fn6(int i,int n){if(i==n){//开始输出acm_1_1_print_one_result6(n);return;}for(int k=1;k<=n;k++){if(vis6[k])continue; //k被使用过了arr6[i]=k;vis6[k]=1;acm_1_1_diGui_fn6(i+1,n);vis6[k]=0; //回收k}
}
void acm_1_1_diGui_test6(){int n; //n代表输入是几 ,m代表每次输出几个数cin >> n;acm_1_1_diGui_fn6(0,n);//0 代表第几个位置//1 代表当前位置最小可以选择的值//n 代表当前位置最大可以选择的值//m 最多枚举多少倍
}
acm_1_1_diGui_test6();

例题:

239不规则的街道

​ 分形系统:

同样的一个图形通过固定的变换到一个更大的图形,-继续更大的图形

//分形图形
void acm_1_1_diGui_fn7(long long n,long long s,long long &x,long long &y){//递归函数,求n级城市中,房子编号为s的房子坐标并将坐标存储在(x,y)变量中if(n==1){//当为1级城市的时候,直接返回if (s==1) x=0,y=0;else if(s==2) x=0,y=1;else if(s==3) x=1,y=1;else x=1,y=0;return;}long long L=1LL << (n-1);long long block=L*L; //每个区域点的数量long long xx,yy;//当前点在第几个区域中if (s <= block ) { //第一个区域,用坐标变换规则:(x,y)->(y,x)acm_1_1_diGui_fn7(n-1,s,xx,yy);x=yy,y=xx;}else if(s <= 2*block){ //第二个区域,(x,y)->(x,y+L)acm_1_1_diGui_fn7(n-1,s-block,xx,yy);x=xx,y=yy+L;}else if(s <= 3*block){ //第三个区域,(x,y)->(x+L,y+L)acm_1_1_diGui_fn7(n-1,s-2*block,xx,yy);x=xx+L,y=yy+L;}else{//第四个区域,(x,y)->(2L-y-1 ,L-x-1)acm_1_1_diGui_fn7(n-1,s-3*block,xx,yy);x=2*L-yy-1,y=L-xx-1;}return;}
void acm_1_1_diGui_test7(){long long t,n,s,d;scanf("%lld",&t);while(t--){scanf("%lld%lld%lld",&n,&s,&d);long long sx,sy,dx,dy;acm_1_1_diGui_fn7(n,s,sx,sy);acm_1_1_diGui_fn7(n,d,dx,dy);printf("%.0lf\n",10*sqrt(S(sx-dx)+S(sy-dy)));}
}
void acm_1_1_diGui_test7(){long long t,n,s,d;scanf("%lld",&t);while(t--){scanf("%lld%lld%lld",&n,&s,&d);long long sx,sy,dx,dy;acm_1_1_diGui_fn7(n,s,sx,sy);acm_1_1_diGui_fn7(n,d,dx,dy);printf("%.0lf\n",10*sqrt(S(sx-dx)+S(sy-dy)));}
}
  • 完成2024.3.5
by cry

这篇关于第1章递归函数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/853663

相关文章

Shell函数:递归函数、阶乘和函数库

文章目录 递归函数示例1:阶乘计算示例2:递归列出目录 函数库 递归函数 递归是指函数在其内部调用自身。递归函数常用于解决像阶乘、斐波那契数列等问题。 示例1:阶乘计算 阶乘(Factorial)是数学中的一种运算,表示从1乘以2乘以3…直到某个数n的乘积,记作n!。 例如: 4! = 1×2×3×4 = 24 (24是4的阶乘)6! = 1×2×3×4×5×6

指针函数、函数指针与递归函数

一.指针函数 1.定义         指针函数是一个函数,其返回值是一个指针         例如:                 void *function()                 int *function()                 float *function() 2.指针函数的返回值         指针函数的返回值要求是 全局变量的地址/st

linux bash shell之递归函数:fork炸弹

所谓fork炸弹是一种恶意程序,它的内部是一个不断在fork进程的无限循环,fork炸弹并不需要有特别的权限即可对系统造成破坏。fork炸弹实质是一个简单的递归程序。由于程序是递归的,如果没有任何限制,这会导致这个简单的程序迅速耗尽系统里面的所有资源。下面是Jaromil设计的最简单的fork炸弹: :() { :|:& };: 或者是 .() { .|.& };. 这么一行只有13个字符

斐波那契的递归函数

斐波那契函数的数学定义 斐波那契的递归实现 #include <stdio.h>int Fbi(int i){if(i<2)return i == 0?0:1;return Fbi(i-1)+Fbi(i-2);}int main(void){int i;for(i = 0;i < 40;i++)printf("[%d] %8d \n",i,Fbi(i));return 0;

C语言入门课程学习笔记8:变量的作用域递归函数宏定义交换变量

C语言入门课程学习笔记8 第36课 - 变量的作用域与生命期(上)第37课 - 变量的作用域与生命期(下)实验—局部变量的作用域实验-变量的生命期 第38课 - 函数专题练习第39课 - 递归函数简介实验小结 第40课 - C 语言中的宏定义实验小结 第36课 - 变量的作用域与生命期(上) #include <stdio.h>int var = 100; // 全

递归函数-汉诺塔经典递归

前言 最近在读《JavaScript语言精粹》,对递归函数有了进一步的认识,希望总结下来: 递归是一种强大的编程技术,他把一个问题分解为一组相似的子问题,每一问题都用一个寻常解去解决。递归函数就是会直接或者间接调用自身的一种函数,一般来说,一个递归函数调用自身去解决它的子问题。 "汉诺塔"经典递归问题 "汉诺塔"是印度的一个古老传说,也是程序设计中的经典的递归问题,是一个著名的益智游戏:

用一个简单的图解方式帮助大家理解递归函数,附送第一阶段PHP串讲总结笔记![PDF整理版]

学习PHP是一个慢慢积累和理解的过程,只有理解才能完整记忆,才能更好的拓展知识点,整合知识点,做出更强大的WEB程序。 今天在这里用图解和言简意赅的描述方式帮助大家理解一下第一阶段的一个难点,递归函数。就当是和大家认识一下。 相信大家上学的时候都学过代数公式吧,类似:公式A=x+y, 其实在PHP里面 函数就是一个公式 实现指定的功能,。比如x+y这样的计算 递归函数不过是在公式里面又套用了

【捷哥浅谈PHP】第四弹---递归函数

很多同学在学习递归函数的时候会感到头晕,无法搞清楚递归函数的原理和运行机制,本文将给大家详细讲解递归函数的运行机制和运用。 那什么是递归函数呢? 递归函数即为自调用函数,在函数体内直接或间接自己调用自己,但需要设置自调用的条件,若满足条件,则调用函数本身,若不满足则终止本函数的自调用,然后把目前流程的主控权交回给上一层函数来执行,可能这样给大家讲解,还是很难明白。 好,那下面我

python递归函数和列表使用

5、斐波那契数列。 程序分析:斐波那契数列(Fibonacci sequence),又称黄金分割数列,指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、…… 斐波那契数列指的是这样一个数列 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597,2584,4181,6765,10946,17711,2865

递归函数的汇编表示

写入程序test.c: # include <stdio.h>int fun(int n){if (n==0)return 0;if(n==1)return 1;elsereturn n+fun(n-1);}int main(){fun(4);return 0;} 使用gcc –g test.c产生调试信息,使用gdb调试程序,反汇编后得到汇编代码(fun函