递归算法题练习(数的计算、带备忘录的递归、计算函数值)

news2024/9/21 14:46:16

目录

递归的介绍

递归如何实现

递归和循环的比较

例题:

(一、斐波那契数列,带备忘录的递归)

如果直接使用递归,难以算出结果,需要优化

 优化方法:带备忘录的递归

(二、数的计算)

(三、计算函数值)

解题思路


递归的介绍

概念:递归是指函数直接或间接调用自身的过程。
解释递归的两个关键要素:
基本情况(递归终止条件):递归函数中的一个条件,当满足该条件时,递归终止,避免无限递归。可以理解为直接解决极小规模问题的方法。递归表达式(递归调用):递归函数中的语句,用于解决规模更小的子问题再将子问题的答案合并成为当前问题的答案。

递归如何实现

递归函数的基本结构如下:
返回类型 函数名(参数列表){
   基本情况(递归终止条件)
if(满足终止条件){
   返回终止条件下的结果
   递归表达式(递归调用)
}
else if{
   将问题分解为规模更小的子问题
   使用递归调用解决子问题
   返回子问题的结果
}

实现过程:

  • 将大问题分解为规模更小的子问题。
  • 使用递归调用解决每个子问题。
  • 通过递归终止条件来结束递归。

设计时需注意的细节:

  1. 确保递归一定能到递归出口,避免无限递归,这可能导致TLE(超时)、MLE(超内存)、或RE(运行错误)
  2. 考虑边界条件,有时候递归出口不止一个。
  3. 避免不必要的重复计算,尽可能优化递归函数的性能(例如使用记忆化)。

递归和循环的比较

递归的特点:

  1. 直观、简洁,易于理解和实现
  2. 适用于问题的规模可以通过递归调用不断减小的情况。
  3. 可以处理复杂的数据结构和算法,如树和图的遍历。(线段树)
  4. 存在栈溢出风险(栈空间一般只有8MB,所以递归层数不宜过深一般不超过1e6层)。

循环的特点:

  • 1.直接控制流程,效率较高。(常数小)
  • 2.适用于问题的规模没有明显的缩减,或者需要特定的迭代次数。(二元组)
  • 3.适合处理大部分的动态规划问题

在部分情况下,递归和循环可以相互转化。(DFS)

例题:

(一、斐波那契数列,带备忘录的递归)

已知F(1)=F(2)= 1;n>3时F(n)=F(n-1)+F(n-2)
输入n,求F(n),n<=100000,结果对1e9+7取模

如果直接使用递归,难以算出结果,需要优化

时间复杂度为O(2^n)

#include <bits/stdc++.h>  
using namespace std;
using ll = long long; // 使用别名ll代表long long  

const int N = 1e5 + 9;
const ll p = 1e9 + 7; // 定义模数p  



ll fib(int n) {
    if (n <= 2) return 1; // 基准情况  
    return (fib(n - 1) + fib(n - 2)) % p; // 计算并存储结果  
}

int main() {
    int n;
    cin >> n;
    for (int i = 1; i <= n; ++i) {
        cout << fib(i) << '\n'; // 输出每个i的fibonacci数并换行  
    }
    return 0;
}

 优化方法:带备忘录的递归

时间复杂度为O(n)

#include <bits/stdc++.h>  
using namespace std;
using ll = long long; // 使用别名ll代表long long  

const int N = 1e5 + 9;
const ll p = 1e9 + 7; // 定义模数p  

ll dp[N]; // 定义dp数组作为备忘录  

// 带备忘录的递归
ll fib(int n) {
    if (dp[n]) return dp[n]; 
    // 如果已经计算过,直接返回结果,不需要重复计算
    if (n <= 2) return 1; // 基准情况  
    return dp[n] = (fib(n - 1) + fib(n - 2)) % p; // 计算并存储结果  
}

int main() {
    int n;
    cin >> n;
    for (int i = 1; i <= n; ++i) {
        cout << fib(i) << '\n'; // 输出每个i的fibonacci数并换行  
    }
    return 0;
}

(二、数的计算)

蓝桥 OJ 760

用户登录

题目描述
输入一个自然数 n(n < 1000),我们对此自然数按照如下方法进行处理:
1.不作任何处理;
2.在它的左边加上一个自然数,但该自然数不能超过原数的一半;

3.加上数后,继续按此规则进行处理,直到不能再加自然数为止。问总共可以产生多少个数。
输入描述
输入一个正整数 n。
输出描述
输出一个整数,表示答案。
输入输出样例

思路:

我们可以将题意转化一下,转化成在右边加上自然数,因为“在左边加上0”是没有意义的,不会改变这个数字大小,所以我们在右边也不能加上0。
用一个数组a记录下数字每一位上的数字是多少,然后枚举当前位上的数字,递归的向下去求方案数并求和即可。

#include<bits/stdc++.h>
using namespace std;

const int N = 20;
int a[N];

int dfs(int dep)// dep表示当前的深度
{
	int res = 1;
	// 枚举当前这层可以放下哪些数字
	for (int i = 1; i <= a[dep - 1] / 2; ++i)
	{
		a[dep] = i;
		res += dfs(dep + 1);
	}
	return res;
}

int main()
{
	int n; cin >> n;
	a[1] = n;
	cout << dfs(2) << '\n';
	return 0;
}

(三、计算函数值)

用户登录

问题描述:

在一个神秘的世界中,有一个传说中的神秘花园,被认为蕴藏着无限的知识。但要进入这个花园,访客必须解决一道神秘数学难题,这个难题与一个特殊的数学函数——“神秘函数”S(c)——紧密相关。

神秘函数S(c)的定义:

  • 当c为0时,S(0) = 1。
  • 当c为偶数时,S(c) = S(c/2)。
  • 当c为奇数时,S(c) = S(c-1) + 1。

任务:

编写一个程序,根据输入的正整数α,计算神秘函数S(α)的值。正确解答这道难题将获得通行证,得以进入神秘花园探索知识宝藏。

输入格式:

输入包含一个正整数α(1 ≤ α ≤ 10^6),表示要求解的神秘函数问题中的参数。

输出格式:

输出一个整数,表示神秘函数S(α)的值,即成功解决问题后得到的答案。

解题思路

这道题主要思想就是递归调用,实现了对递推方程的求解问题。

首先,我们定义一个函数,它所实现的功能是返回通过神秘函数运算得到的值。

那么,我们可以分为三个部分:

  1. 当 x=0 时,我们知道通过神秘函数运算得到的值为 1,因此直接返回 1。
  2. 当 x 为偶数时,由于 S(x)=S(x/2),故我们只需要计算 S(x/2) 的值并返回即可,这时我们再次调用我们定义的函数并以 x/2 为初始值。
  3. 当 x 为奇数时,由于 S(x)=S(x−1)+1,故我们只需要计算S(x−1) 的值并返回 S(x−1)+1 即可,这时我们再次调用我们定义的函数并以 x−1 为初始值。

经过如上过程便可以得出最终结果。

#include <bits/stdc++.h>

// 奇数减一会变成偶数,偶数除以2
// 等价与我们最多使用两次代价使 x 除以 2
// 除以 2 最多 log 次
// O(log)

void solve(const int &Case) { 
    int x;
    std::cin >> x;
    std::function<int(int)> S = [&](int x) {
        if (x == 0)return 1;
        if (x % 2 == 0) {
            return S(x / 2);
        }
        return S(x - 1) + 1;
    };
    std::cout << S(x) << '\n';
}

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    int T = 1;
    for (int i = 1; i <= T; i++)solve(i);
    return 0;
}

 今天就先到这了!!!

看到这里了还不给博主扣个:
⛳️ 点赞☀️收藏 ⭐️ 关注!

你们的点赞就是博主更新最大的动力!
有问题可以评论或者私信呢秒回哦。

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

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

相关文章

【Linux进程】进程状态(运行阻塞挂起)

目录 前言 1. 进程状态 2. 运行状态 3. 阻塞状态 4. 挂起状态 5. Linux中具体的状态 总结 前言 在Linux操作系统中&#xff0c;进程状态非常重要&#xff0c;它可以帮助我们了解进程在系统中的运行情况&#xff0c;从而更好地管理和优化系统资源&#xff0c;在Linux系统中&am…

3D城市模型可视化:开启智慧都市探索之旅

随着科技的飞速发展&#xff0c;我们对城市的认知已经不再局限于平面的地图和照片。今天&#xff0c;让我们领略一种全新的城市体验——3D城市模型可视化。这项技术将带领我们走进一个立体、生动的城市世界&#xff0c;感受前所未有的智慧都市魅力。 3D城市模型通过先进的计算机…

Harbor高可用(haproxy和keepalived)

Harbor高可用&#xff08;haproxy和keepalived&#xff09; 文章目录 Harbor高可用&#xff08;haproxy和keepalived&#xff09;1.Harbor高可用集群部署架构1.1 主机初始化1.1.1 设置网卡名和ip地址1.1.2 设置主机名1.1.3 配置镜像源1.1.4 关闭防火墙1.1.5 禁用SELinux1.1.6 设…

Java 下载excel文件

一、背景 微信小程序需要导出excel文件&#xff0c;后端技术Java&#xff0c;前端使用uniapp框架&#xff0c;使用excel模板。 二、excel 报表模板 需要补充的内容是以下标记问号的&#xff0c;其中有个表格&#xff0c;内容是动态添加的 三、Java端代码实现 关键步骤&…

SVPWM

SVPWM SVPWMSVPWM原理产品比较特点来源 SVPWM SVPWM的主要思想是以三相对称正弦波电压供电时三相对称电动机定子理想磁链圆为参考标准&#xff0c;以三相逆变器不同开关模式作适当的切换&#xff0c;从而形成PWM波&#xff0c;以所形成的实际磁链矢量来追踪其准确磁链圆。传统…

如何设置从小程序跳转到其它小程序

​有的商家有多个小程序&#xff0c;希望能够通过一个小程序链接到所有其它小程序&#xff0c;用户可以通过点击跳转链接实现从一个小程序跳转到另一个小程序。要怎么才能实现这样的跳转呢。下面具体介绍。 1. 设置跳转。在小程序管理员后台->分类管理&#xff0c;添加一个…

【开源】JAVA+Vue.js实现天沐瑜伽馆管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 瑜伽课程模块2.3 课程预约模块2.4 系统公告模块2.5 课程评价模块2.6 瑜伽器械模块 三、系统设计3.1 实体类设计3.1.1 瑜伽课程3.1.2 瑜伽课程预约3.1.3 系统公告3.1.4 瑜伽课程评价 3.2 数据库设计3.2.…

C++与 Fluke5500A设备通过GPIB-USB-B通信的经验积累

C与 Fluke5500A设备通过GPIB-USB-B通信的经验积累 以下内容来自&#xff1a;C与 Fluke5500A设备通过GPIB-USB-B通信的经验积累 - JMarcus - 博客园 (cnblogs.com)START 1.需要安装NI-488.2.281&#xff0c;安装好了之后&#xff0c;GPIB-USB-B的驱动就自动安装好了 注意版本…

苍穹外卖Day03——解决总结3中存在的问题

解决Day03中存在的问题 1. ResponseBody 与 RequestBody2. RequestParam 与 PathVariable3. 字段填充技术&#xff08;注解、AOP、反射&#xff09;3.1. AOP3.2. 注解3.3. 反射3.5 字段填充在项目应用 4. 阿里云云存储OOS 1. ResponseBody 与 RequestBody ResponseBody&…

Docker容器与虚拟化技术:OpenEuler 使用 docker-compose 部署 LNMP

目录 一、实验 1.环境 2.OpenEuler 部署 docker-compose 3.docker-compose 部署 LNMP 二、问题 1.ntpdate未找到命令 2.timedatectl 如何设置时区与时间同步 3.php网页显示时区不对 一、实验 1.环境 &#xff08;1&#xff09;主机 表1 主机 系统架构版本IP备注Lin…

事物

概述&#xff1a; 数据库的事务&#xff08;Transaction&#xff09;是一种机制、一个操作序列&#xff0c;包含了一组数据库操作命令。 事务把所有的命令作为一个整体一起向系统提交或撤销操作请求&#xff0c;即这一组数据库命令要么同时成功&#xff0c;要么同时失败。 事…

大模型量化技术原理-ZeroQuant系列

近年来&#xff0c;随着Transformer、MOE架构的提出&#xff0c;使得深度学习模型轻松突破上万亿规模参数&#xff0c;从而导致模型变得越来越大&#xff0c;因此&#xff0c;我们需要一些大模型压缩技术来降低模型部署的成本&#xff0c;并提升模型的推理性能。 模型压缩主要分…

神经网络系列---卷积

文章目录 卷积神经网络卷积转置卷积 卷积核和反卷积的三种实现方式卷积的次数计算 卷积神经网络 在神经网络的卷积层中&#xff0c;向下取整&#xff08;Floor&#xff09;是一种常用的策略&#xff0c;特别是在处理输出尺寸不是整数的情况时。当你计算出卷积层输出的尺寸&…

回溯例题(leetcode17/37)

文章目录 leetcode37leetcode17 回溯跟枚举差不多。要注意“回溯”&#xff0c;别忘记“回”之前把之前的改动都复原。 leetcode37 leetcode37是解数独问题。本题保证有且仅有唯一解。 思路&#xff1a;先把空格子的位置存下来&#xff0c;然后对每一个空位置挨个枚举1-9。枚…

Vue2:用node+express部署Vue项目

一、编译项目 命令 npm run build执行命令后&#xff0c;我们会在项目文件夹中看到如下生成的文件 二、部署Vue项目 接上一篇&#xff0c;nodeexpress编写轻量级服务 1、在demo中创建static文件夹 2、将dist目录中的文件放入static中 3、修改server.js文件 关键配置&…

小红书关键词爬虫

标题 1 统计要收集的关键词&#xff0c;制作一个文件夹2 爬取每一页的内容3 爬取标题和内容4 如果内容可以被查看&#xff0c;爬取评论内容5 将结果进行汇总&#xff0c;并且每个帖子保存为一个json文件&#xff0c;具体内容6 总结 1 统计要收集的关键词&#xff0c;制作一个文…

【白嫖8k买的机构vip教程】Appium自动化(3):Appium-Desktop界面介绍

Appium-Desktop主界面包含三个菜单Simple、Advanced、Presets Simple界面&#xff1a; Host设置Appium server的ip地址&#xff0c;本地调试可以将ip地址修改为127.0.0.1&#xff1b;Port设置端口号&#xff0c;默认是4723不用修改Start Server 启动 Appium serverEdit Confi…

优思学院|质量工程师需要学习什么软件?

初入职质量工程师的朋友常常会问&#xff1a;质量工程师需要学习什么软件&#xff1f;在质量控制和管理的世界里&#xff0c;拥有强大的数据分析工具是走向成功的关键&#xff0c;因此&#xff0c;对于质量工程师来说&#xff0c;掌握正确的软件不仅能提升工作效率&#xff0c;…

多输入多输出 | Matlab实现RIME-BP霜冰算法优化BP神经网络多输入多输出预测

多输入多输出 | Matlab实现RIME-BP霜冰算法优化BP神经网络多输入多输出预测 目录 多输入多输出 | Matlab实现RIME-BP霜冰算法优化BP神经网络多输入多输出预测预测效果基本介绍程序设计往期精彩参考资料 预测效果 基本介绍 多输入多输出 | Matlab实现RIME-BP霜冰算法优化BP神经网…

深度学习-神经网络原理

文章目录 神经网络原理1.单层神经网络1.1 回归单层神经网络&#xff1a;线性回归1.2 二分类单层神经网络&#xff1a;sigmoid与阶跃函数 1.3 多分类单层神经网络&#xff1a;softmax回归 神经网络原理 人工神经网络&#xff08;Artificial Neural Network&#xff0c;ANN&…