算法篇 篇一:递归和递推(Java)

本系列用来记录本人所学的基础算法,为了更好的复习!如果能给你带来帮助也是我的荣幸!!

如果有错误欢迎指出!也欢迎在评论区里评论!

废话不多说开始!

递归

什么是递归

本人的理解是:递归就是函数的套娃!函数里又调用了自己本身的函数(只是在调用时传入的参数不同罢了),而通过本身里的调用来达到目的或者将目的化成更小的目的,最后大事化小,小事化了,拿最简单的例子来举例:

比如要求n的阶层

刚刚开始没接触递归的时候,用的是for循环:

import java.util.*;
public class Main {
	public static void main(String []arges) {
		Scanner sc=new Scanner(System.in);
		long sum=1;
		int n=sc.nextInt();
		for(int i=1;i<=n;i++) {
			sum*=i;
		}
		System.out.println(sum);
	}
}

而要用递归的话就要想想怎么把大事化小了吧

n的阶层不就是n*(n-1)的阶层吗

而n-1的阶层不就是(n-1)*(n-2)的阶层吗

依从来看的话

那我是不是可以用一个函数来通过递归(函数的套娃)来实现呐?

试试看!

import java.util.*;
public class Main {
	public static void main(String []arges) {
		Scanner sc=new Scanner(System.in);
		long sum=1;
		int n=sc.nextInt();
		sum*=fun(n);
		System.out.println(sum);
	}
	public  static long fun(int x) {
		if(x>=2) return x*fun(x-1);
		return 1;
	}
}

试试看输出,yes!!输入5 结果都是120,nice!!

这样一看是不是简单的递归就实现啦!!

--------------------以上是本人的学习记录-------------------

来看看大佬的解题思路嘿嘿嘿

以下文献来自于https://zhuanlan.zhihu.com/p/94748605icon-default.png?t=N7T8https://zhuanlan.zhihu.com/p/94748605

递归算法通用解决思路

我们在上一节仔细剖析了什么是递归,可以发现递归有以下两个特点

  1. 一个问题可以分解成具有相同解决思路的子问题,子子问题,换句话说这些问题都能调用同一个函数
  2. 经过层层分解的子问题最后一定是有一个不能再分解的固定值的(即终止条件),如果没有的话,就无穷无尽地分解子问题了,问题显然是无解的。

所以解递归题的关键在于我们首先需要根据以上递归的两个特点判断题目是否可以用递归来解。

经过判断可以用递归后,接下来我们就来看看用递归解题的基本套路(四步曲):

  1. 先定义一个函数,明确这个函数的功能,由于递归的特点是问题和子问题都会调用函数自身,所以这个函数的功能一旦确定了, 之后只要找寻问题与子问题的递归关系即可
  2. 接下来寻找问题与子问题间的关系(即递推公式),这样由于问题与子问题具有相同解决思路,只要子问题调用步骤 1 定义好的函数,问题即可解决。所谓的关系最好能用一个公式表示出来,比如 f(n) = n * f(n-) 这样,如果暂时无法得出明确的公式,用伪代码表示也是可以的, 发现递推关系后,要寻找最终不可再分解的子问题的解,即(临界条件),确保子问题不会无限分解下去。由于第一步我们已经定义了这个函数的功能,所以当问题拆分成子问题时,子问题可以调用步骤 1 定义的函数,符合递归的条件(函数里调用自身)
  3. 将第二步的递推公式用代码表示出来补充到步骤 1 定义的函数中
  4. 最后也是很关键的一步,根据问题与子问题的关系,推导出时间复杂度,如果发现递归时间复杂度不可接受,则需转换思路对其进行改造,看下是否有更靠谱的解法

递推

什么是递推 

递推感觉有点像递归的兄弟,2个人很像但又不完全一样。递归有点像知道题解去要过程,而递推有点像从过程去要题解。感觉从实现上来说递推会更难一点(作者是一个菜狗)所以直接来康康大佬的思路吧 顺便做个学习笔记!!

学习文献来自https://www.cnblogs.com/skyme/p/3541863.html#:~:text=%E9%80%92%E6%8E%A8%E7%AE%97%E6%B3%95%E6%98%AF%E4%B8%80,%E7%9B%B4%E5%88%B0%E6%B1%82%E5%87%BA%E5%87%BD%E6%95%B0%E5%80%BC.&text=%E7%94%B1%E6%AD%A4%E5%8F%AF%E8%A7%81%2C%E9%80%92%E6%8E%A8,%E5%BA%94%E5%B0%BD%E9%87%8F%E4%BD%BF%E7%94%A8%E9%80%92%E6%8E%A8.icon-default.png?t=N7T8https://www.cnblogs.com/skyme/p/3541863.html#:~:text=%E9%80%92%E6%8E%A8%E7%AE%97%E6%B3%95%E6%98%AF%E4%B8%80,%E7%9B%B4%E5%88%B0%E6%B1%82%E5%87%BA%E5%87%BD%E6%95%B0%E5%80%BC.&text=%E7%94%B1%E6%AD%A4%E5%8F%AF%E8%A7%81%2C%E9%80%92%E6%8E%A8,%E5%BA%94%E5%B0%BD%E9%87%8F%E4%BD%BF%E7%94%A8%E9%80%92%E6%8E%A8.

--------------------------------------------------------------------------------------------------------------------------------

递推算法是一种简单的算法,即通过已知条件,利用特定关系得出中间推论,直至得到结果的算法。
递推算法分为顺推和逆推两种。

相对于递归算法,递推算法免除了数据进出栈的过程,也就是说,不需要函数不断的向边界值靠拢,而直接从边界出发,直到求出函数值.
比如阶乘函数:f(n)=n*f(n-1)
在f(3)的运算过程中,递归的数据流动过程如下:
f(3){f(i)=f(i-1)*i}-->f(2)-->f(1)-->f(0){f(0)=1}-->f(1)-->f(2)--f(3){f(3)=6}
而递推如下:
f(0)-->f(1)-->f(2)-->f(3)
由此可见,递推的效率要高一些,在可能的情况下应尽量使用递推.但是递归作为比较基础的算法,它的作用不能忽视.所以,在把握这两种算法的时候应该特别注意。

顺推

所谓顺推法是从已知条件出发,逐步推算出要解决的问题的方法叫顺推。
如斐波拉契数列,设它的函数为f(n),已知f(1)=1,f(2)=1;f(n)=f(n-2)+f(n-1)(n>=3,n∈N)。则我们通过顺推可以知道,f(3)=f(1)+f(2)=2,f(4)=f(2)+f(3)=3……直至我们要求的解。

逆推

所谓逆推法从已知问题的结果出发,用迭代表达式逐步推算出问题的开始的条件,即顺推法的逆过程,称为逆推

是不是听的有点懵懵的呀

上题来实践一下就清楚多啦!!

例题

【案例】从原点出发,一步只能向右走、向上走或向左走。恰好走N步且不经过已走的点共有多少种走法?

样例输入:N=2

样例输出:result=7

样例输入:N=3

样例输出:result=17

答案会放在评论区哟

给大家一下思路康康能不能自己写出来呐!

解题思路:要解决走N步共有多少种走法,我们在拿到题目的时候最直接的想法就是先画出当N=1、N=2、N=3。。。。。N=n时对应走法的图例,由简单到复杂、由特殊到一般的推理过程,找出规律获得解题的思路。在数学上,我们称为归纳法。如果用编程的方法来求解这样的推理题,我们把这样的求解思路(算法)称之为递推法。递推的精髓在于f(n)的结果一般由f(n-1)、f(n-2)…..f(n-k)的前k次结果推导出来。我们在解决这类递推问题时,难点就是如何从简单而特殊的案例,找到问题的一般规律,写出f(n)与f(n-1)、f(n-2)…..f(n-k)之间的关系表达式,从而得出求解的结果。在历年noip的复赛当中,参赛选手对于这类题目都有这样的感受,往往花费了大量的时间来分析题目的一般规律,写出f(n)的一般表达式,而编程实现可能只需要几分钟的时间。所以我们在平时训练的时候,对于这样的递推题目,就必须掌握如何分析问题,从特殊推导出一般的规律,写出想要的关系表达式,问题就迎刃而解了。下面是这道题解题的心得,供大家参考:

(1)当N=1时,绘出走法图

(图1)共有3种不同的走法,也就是黑色线条的数量,即f(1)=3

(2)当N=2时,绘出走法图

(图2)共有7种不同的走法,也就是绿色线条的数量,即f(2)=7

(3)当N=3时,绘出走法图

(图3)共有17种不同的走法,也就是红色线条的数量,即f(3)=17

由此,我们不难看出,对于任何一个起点,最多可以走出3种走法,但最少必须走出2种走法。那么我们要求出f(n),实际上转换为如果我们能够得到上一步即f(n-1)有多少个终点是有3种走法的,有多少个点有2种走法的,那么问题就解决了。

a. 上一步,即f(n-1)有多少个终点是有3种走法的。

       对于N=3时,f(n-1)=f(2), 有3个点A、B、C可以走出3种不同走法的,这3个点是怎么得到的呢?它的存在与N值有没有必然的联系?如果我们能找到它与N之间的关系,问题也就解决了。有了这样的思路以后,我们不难找到这样的规律:如果f(n-2)存在,即上上步存在,那么从上上步出发的线路里面必然会有一条向上走的线路,而这条向上走的线路在到达f(n-1)之后,  向f(n)出发时也必然有左、上、右这三种走法,那么我们就得出了这样的结论:当f(n-2)存在时,f(n-2)的值实际上就等价于f(n-1)有多少个终点是有3种走法。

         b.    f(n-1)有多少个终点是有2种走法的

对于N=3时,有4个点D、E、F、G可以走出2种不同走法的,这4个点又是怎么得到的呢?它与N值有什么联系呢? 实际上我们在解决了上一个问题的时候,这个问题就变得相当容易了, f(n-1)减掉刚才有3种走法的点,剩下的点不就是只有2种走法了吗?即f(n-1)-f(n-2)。

    c. 得出f(n)的一般关系式

f(n)=3*f(n-2)+2*(f(n-1)-f(n-2) ) (n>=3)

化简:

f(n)=2*f(n-1)+f(n-2) (n>=3)

      有一点需要补充的就是,任何递推题,都会有临界条件。当N=1时,f(n)=3;,当N=2时,f(n)=7,这些都可以看成是临界条件。只有当N>=3时,即上上步存在的情况下,就可以得出f(n)的一般通式:f(n)=2*f(n-1)+f(n-2)

答案放在评论区啦!!

为了更好的做题就不放在正文啦

ok收工晚安~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值