递归函数学习 part1

一,初始递归:阶乘

1,原理

n的阶乘等于n乘以n-1的阶乘,而0的阶乘等于1.

2,代码展示

#include <iostream>
using namespace std;int fact(int);
int main()
{cout<<fact(5);return 0;
}int fact(int n)
{if(n==0) return 1;return n * fact(n-1);
}

二,深化理解:斐波那契数列

1,原理

当n小于等于2时,f(n)= 1;当大于2时,f(n) = f (n-1) + f(n-2).

2,代码展示

a,暴力复杂的方法,复杂度成几何形式增长

#include<iostream>using namespace std;int Fibonacci(int);int main()
{cout << Fibonacci(30);return 0;
}int Fibonacci(int n)
{if (n == 1 || n == 2) return 1;return Fibonacci(n - 1) + Fibonacci(n - 2);
}

我的电脑在n 等于100时,就半天跑不出来结果了。

b,动态规划

直接使用数组,不使用函数递归。

int Fibonacci(int n)
{if (n == 1 || n == 2) return 1;int* dp = new int[n + 1];dp[0] = 0;dp[1] = 1;if (n == 1 || n == 0) return 1;for (int i = 2; i < n + 1; i++){dp[i] = dp[i - 1] + dp[i - 2];}int result = dp[n];delete[] dp;return result;}

注意点:

1,动态规划设置数组大小

在c语言里你不能用dp[n]来声明一个大小为n的数组。因为数组的大小是在程序运行前就已经确定好了的,所以只能手动设置大小。有两种方法:new 和malloc。

2,数组大小设置为n+1

在斐波那契数列的动态规划实现中,你必须声明一个大小为 n+1 的数组,而不能直接声明大小为 n 的数组。原因如下:

1). 数组下标从 0 开始

数组的下标是从 0 开始的,因此如果你声明一个大小为 n 的数组,它的有效下标范围是 0 到 n-1,没有包含 n 这个位置。而为了存储第 n 个斐波那契数,你需要一个包含 dp[n] 的数组元素。因此,数组的大小应该为 n+1,以确保能够存储到 dp[n]

2). 存储斐波那契数列的所有元素

在动态规划中,你需要存储从 F(0) 到 F(n) 的所有值,以便逐步计算每个值。如果你只分配了 n 个位置,那么 dp[n] 这一位置会超出数组的范围,导致访问越界错误。

举例:

假设 n = 5,你需要存储 dp[0] 到 dp[5],总共 6 个元素。如果你只分配了一个大小为 n = 5 的数组,那么该数组的有效下标是 0, 1, 2, 3, 4,而你需要 dp[5],这就会访问越界,从而导致错误。

3,结果溢出

如果最后计算出来的结果超过了 int 类型所能表示的范围,通常会出现 整数溢出(integer overflow)。在这种情况下,计算结果会“回绕”,导致存储在 int 变量中的结果变成一个非常大的负数。这是因为 int 类型有一个固定的取值范围,如果超出了这个范围,它会从最小值重新开始,表现为负数。

int 类型的范围

在大多数平台(例如,32 位系统)上,int 类型的取值范围通常是:

  • 最小值:-2,147,483,648 (即 −231−231)
  • 最大值:2,147,483,647 (即 231−1231−1)

如果计算结果超出了这个范围,C 语言没有内建的检查机制来防止溢出,而是继续执行,导致溢出行为,并将结果存储在 int 类型的范围内。

举个例子:

假设你的系统上 int 的范围是 -2,147,483,648 到 2,147,483,647。如果你计算一个很大的斐波那契数(例如第 50 个斐波那契数,12586269025),它明显超出了 int 的范围,结果会变成负数,导致输出类似于 -2147483647 或其他类似的负数值。

为什么会显示负数?

如果结果超出了 int 能存储的最大值,计算机会“回绕”到最小值,继续在负数范围内计算,最终显示的是一个负数。实际的计算过程如下:

  1. 计算出一个超出范围的值。
  2. 由于 int 的最大范围为 2,147,483,647,当结果大于这个值时,数值会“回绕”到负数范围,得到一个负值。

c,空间优化的动态规划

1,原理

类似链表更新节点,我们可以发现求斐波那契值只涉及到前面两个数字,所以使用三个局部变量来实现更新。

2,代码展示
int Fibonacci(int n)
{if (n == 1 || n == 2) return 1;int current = 0, prev1 = 1, prev2 = 1;for (int i = 3; i < n + 1; i++){current = prev1 + prev2;prev1 = prev2;prev2 = current;}return current;
}

相比于动态规划,这个方法极大地节省空间,减低空间复杂度。

d,矩阵快速幂

涉及到矩阵计算,有点复杂,需要前置知识。

1,原理

2,代码展示

a,矩阵乘法

补充:矩阵怎么作为参数传参

  • 使用指针:最常见的方式,适用于动态数组或不确定大小的数组。
  • 使用数组类型声明:当数组的大小已知时(如固定行列数),可以直接在函数签名中声明数组的尺寸。
  • 指向指针的指针:处理动态二维数组或不规则二维数组时非常有用。
  • typedef 定义类型:为二维数组定义新的类型,代码更加简洁和可读。
void matrixmultiply(int F[2][2], int M[2][2])
{int x = F[0][0] * M[0][0] + F[0][1] * M[1][0];int y = F[0][0] * M[0][1] + F[0][1] * M[1][1];int z = F[1][0] * M[0][0] + F[1][1] * M[1][0];int w = F[1][0] * M[0][1] + F[1][1] * M[1][1];F[0][0] = x;F[0][1] = y;F[1][0] = z;F[1][1] = w;
}

这是对于两行两列矩阵。

b,矩阵的幂

void matrixpowder(int F[2][2], int n)
{if (n == 0 || n == 1) return;//when n is 0 or 1,the matrix dont need processingint M[2][2] = { {1,1},{1,0} };matrixpowder(F, n / 2);matrixmultiply(F, F);if (n % 2 != 0) matrixmultiply(F, M);
}

 这里用到了递归算法

接下来是解释这串代码:

首先传入的参数F,必须是用于计算斐波那契数列的标准矩阵。数学原理如下:

即求F(n)就是算M的n-1次幂后的矩阵(假设为A)的第一行第一列元素。

然后是if语句判断,当n=1或0时,0是单位矩阵,1是其本身,不做处理。

matrixpowder(F, n / 2);

这行是利用二分法求高幂次的矩阵,对于偶数次幂,二分求F的n/2次幂。一直二分直至n=1或0.后面有矩阵乘法。

	matrixmultiply(F, F);

注意这里的F不再是传入的F,而是二分后的F,所以算的是计算矩阵 Fn=Fn/2×Fn/2Fn=Fn/2×Fn/2

最后的代码是用于处理幂是奇数,即

  • 对于奇数 n,Fn=Fn−1×Fn=Fn−1×F,即矩阵的 n 次方可以通过先计算 Fn−1 再乘以 F 来得到。
  • 这里,matrixMultiply(F, M) 用于将矩阵 F 再乘上矩阵 M,从而补偿掉少计算的一次矩阵乘法。
    • 如果 n=5,首先计算 F2 并将其平方得到 F4,然后再与 M 相乘得到 F5。

完整代码展示

#include<iostream>using namespace std;void matrixmultiply(int F[2][2], int M[2][2]);
void matrixpowder(int F[2][2], int);
int Fibonacci(int);int main()
{cout << Fibonacci(10) << endl;return 0;
}void matrixmultiply(int F[2][2], int M[2][2])
{int x = F[0][0] * M[0][0] + F[0][1] * M[1][0];int y = F[0][0] * M[0][1] + F[0][1] * M[1][1];int z = F[1][0] * M[0][0] + F[1][1] * M[1][0];int w = F[1][0] * M[0][1] + F[1][1] * M[1][1];F[0][0] = x;F[0][1] = y;F[1][0] = z;F[1][1] = w;
}void matrixpowder(int F[2][2], int n)
{if (n == 0 || n == 1) return;//when n is 0 or 1,the matrix dont need processingint M[2][2] = { {1,1},{1,0} };matrixpowder(F, n / 2);matrixmultiply(F, F);if (n % 2 != 0) matrixmultiply(F, M);
}int Fibonacci(int n)
{if (n == 1 || n == 2) return 1;int F[2][2] = { {1,1},{1,0} };// the standard matrix for calculating the power of matrixmatrixpowder(F, n - 1);return F[0][0];
}
优点:
  • 时间复杂度:O(log⁡n)O(logn)(通过快速幂)
  • 空间复杂度:O(1)O(1)

e,黄金分割法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/12368.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

开源 - Ideal库 -获取特殊时间扩展方法(四)

书接上回&#xff0c;我们继续来分享一些关于特殊时间获取的常用扩展方法。 01、获取当前日期所在月的第一个指定星期几 该方法和前面介绍的获取当前日期所在周的第一天&#xff08;周一&#xff09;核心思想是一样的&#xff0c;只是把求周一改成求周几而已&#xff0c;当然其…

Python练习18

Python日常练习 题目&#xff1a; 请编fun函数&#xff0c;求44整型数组的主对角线元素的和。 说明&#xff1a; 如下图所示为一个44整型数组 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 测试用例&#xff1a; 1 2 3 4 5 6 7 8…

智防未戴帽,安全无死角

在追求高效与安全并重的现代工业环境中&#xff0c;员工佩戴安全帽作为最基本的防护措施&#xff0c;其重要性不言而喻。为了有效杜绝员工未佩戴安全帽的现象&#xff0c;我们提出了一套以AI视频分析与安全教育培训系统为核心的综合解决方案&#xff0c;旨在通过智能化手段与系…

C++ 优先算法 —— 四数之和(双指针)

目录 题目&#xff1a;四数之和 1. 题目解析 2. 算法原理 Ⅰ. 暴力枚举 Ⅱ. 双指针算法 不漏的处理&#xff1a; 去重处理&#xff1a; 3. 代码实现 Ⅰ. 暴力枚举 Ⅱ. 双指针算法 题目&#xff1a;四数之和 1. 题目解析 题目截图&#xff1a; 这道题与三数之和&am…

[vulnhub] Corrosion: 2

https://www.vulnhub.com/entry/corrosion-2,745/ 提示&#xff1a;枚举才是神 主机发现端口扫描 使用nmap扫描网段类存活主机 因为靶机是我最后添加的&#xff0c;所以靶机IP是6 &#xff0c;kali是10 nmap -sP 192.168.56.0/24 Starting Nmap 7.94SVN ( https://nmap.org ) …

前端请求后端php接口跨域 cors问题

只需要后端在网站的入口文件 一般都是 index.php 加上 这几行代码就可以了 具体的参数可以根据需要去修改 header("Access-Control-Allow-Origin: *"); header(Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS); header(Access-Control-Allow-Heade…

【星闪EBM-H63开发板】AT固件的配置与测试

引言 前面的博客已经介绍了【星闪EBM-H63开发板】小熊派固件中心的使用_bearpi-bm h63固件烧录工具-CSDN博客和【星闪EBM-H63开发板】固件的烧录-CSDN博客&#xff0c;今天来测试一下另一种固件&#xff0c;也就是AT固件。有关AT固件的介绍参见&#xff1a;【星闪EBM-H63开发板…

Linux基础(十四)——BASH

BASH 1.BASH定义2.shell的种类3.bash的功能3.1 命令记录功能3.2 命令补全功能3.3 命令别名设置3.4 工作控制、 前景背景控制3.5 程序化脚本&#xff1a; &#xff08; shell scripts&#xff09;3.6 万用字符 4.bash的内置命令5.shell的变量功能5.1 变量的取用5.2 新建变量5.3 …

【前端学习笔记】JavaScript学习一【变量与数据类型】

一、变量 变量是计算机中用来存储数据的“容器”&#xff0c;通俗的理解变量就是使用【某个符号】来代表【某个具体的数值】&#xff08;数据&#xff09; 声明&#xff1a;声明(定义)变量有两部分构成&#xff1a;关键字 变量名 JavaScript 使用关键字 let 和 var 来声明&am…

使用Git工具在GitHub的仓库中上传文件夹(超详细)

如何使用Git工具在GitHub的仓库中上传文件夹&#xff1f; 如果觉得博主写的还可以&#xff0c;点赞收藏关注噢~ 第一步&#xff1a;拥有一个本地的仓库 可以fork别人的仓库或者自己新创建 fork别人的仓库 或者自己创建一个仓库 按照要求填写完成后&#xff0c;点击按钮创建…

Linux kernel 堆溢出利用方法(二)

前言 本文我们通过我们的老朋友heap_bof来讲解Linux kernel中off-by-null的利用手法。在通过讲解另一道相对来说比较困难的kernel off-by-null docker escape来深入了解这种漏洞的利用手法。&#xff08;没了解过docker逃逸的朋友也可以看懂&#xff0c;毕竟有了root权限后&a…

福昕阅读器高级版解决文件上传IEEE PDF eXpress字体未嵌入

文件上传IEEE PDF eXpress字体未嵌入问题 Errors: Font Arial-BoldMT, Arial-ItalicMT, ArialMT is not embedded (93x on pages 2-3,5) 因为没安装adobe&#xff0c;尝试使用福昕阅读器高级版解决&#xff08;学校统一买的&#xff0c;不知道普通版行不行&#xff09; 找到潜…

人工智能在智能家居的应用

AI 在智能家居场景中&#xff0c;一方面将进一步推动家居生活产品的智能化&#xff0c;包 括照明系统、音箱系统、能源管理系统、安防系统等&#xff0c;实现家居产品从感知到认知再到决策的 发展&#xff1b;另一方面在于智能家居系统的建立&#xff0c;搭载人工智能的多款产品…

如何管理好自己的LabVIEW项目

在LabVIEW项目开发中&#xff0c;项目管理对于提高开发效率、确保项目质量、减少错误和维护成本至关重要。以下从项目规划、代码管理、测试与调试、版本控制、团队协作等方面&#xff0c;分享LabVIEW项目管理的体会。 ​ 1. 项目规划与需求分析 关键步骤&#xff1a; 需求分析…

51c自动驾驶~合集10

我自己的原文哦~ https://blog.51cto.com/whaosoft/11638131 #端到端任务 说起端到端&#xff0c;每个从业者可能都觉得会是下一代自动驾驶量产方案绕不开的点&#xff01;特斯拉率先吹响了方案更新的号角&#xff0c;无论是完全端到端&#xff0c;还是专注于planner的模型&a…

vs2022搭建opencv开发环境

1 下载OpenCV库 https://opencv.org/ 下载对应版本然后进行安装 将bin目录添加到系统环境变量opencv\build\x64\vc16\bin 复制该路径 打开高级设置添加环境变量 vs2022新建一个空项目 修改属性添加头文件路径和库路径 修改链接器&#xff0c;将OpenCV中lib库里的o…

蓝牙音响音频功放:【矽源特HAA9809 AB+D类自动切换】

目录 1&#xff1a;HAA9809特性 2&#xff1a;典型应用电路 3&#xff1a;CTRL管脚控制信息 4&#xff1a;一线脉冲控制方式 5&#xff1a;输入电阻&#xff0c;调节放大增益 6&#xff1a;输入电容&#xff0c;调节频响 7&#xff1a;总结 矽源特ChipSourceTek-HAA9809…

大语言模型安全,到底是什么的安全

什么是AI安全 自ChatGPT问世以来&#xff0c;市场上涌现出了众多大型语言模型和多样化的AI应用。这些应用和模型在为我们的生活带来便利的同时&#xff0c;也不可避免地面临着安全挑战。AI安全&#xff0c;即人工智能安全&#xff0c;涉及在人工智能系统的开发、部署和使用全过…

云岚到家 秒杀抢购

目录 秒杀抢购业务特点 常用技术方案 抢券 抢券界面 进行抢券 我的优惠券列表 活动查询 系统设计 活动查询分析 活动查询界面显示了哪些数据&#xff1f; 面向高并发如何提高活动查询性能&#xff1f; 如何保证缓存一致性&#xff1f; 数据流 Redis数据结构设计 如…

餐饮点餐系统(2)

今天我们继续完成我们的项目&#xff0c;本次的目标是为每一个分支选项&#xff0c;创建菜单。 分析&#xff1a;1.首先我们要为每一个分支选项创建一个函数 2.其次是调用我们创建的函数 3.最后创建的自定义函数中会用到&#xff0c;while语句&#xff0c;switch语句&#xff…