《算法笔记》总结No.5——递归

一.分而治之

将原问题划分为若干个规模较小而结构与原问题相同或相似的子问题,然后分别解决这些子问题,最后合并子问题的解,即可得到原问题的解,步骤抽象如下:

  1. 分解:将原问题分解为若干子问题
  2. 解决:递归求解所有子问题,如果子问题的规模小到可以直接解决,就直接解决它
  3. 合并:将子问题的解合并为原问题的解

子问题之间应该是相互独立且没有交叉的,从严格的定义上将,子问题个数为1的情况称为减治,而大于1的情况称为分治。

分治法作为一种思想,即可使用递归的手段去实现,也可以通过非递归的手段去实现。

二.递归

递归的一个很符合精髓且搞笑的定义:要理解递归,你要先理解递归,直到你能理解递归为止

递归的核心在于——反复调用自身函数,但是每次能把问题范围缩小,直到范围缩小到可以直接得到边界数据的结果,然后再在返回的路上求出对应的解。

两个重要概念:

  • 递归边界:分解问题的尽头
  • 递归式(或者称之为递归调用、递归函数):分解子问题的手段

        如果使用递归而式而不进行阻止,那么最后将会无法停止这个黑洞似的无穷尽的算法。递归的代码结构中移动存在上述两个概念,他们支撑起了整个递归最关键的逻辑。

三.递归计算阶乘

直接先上代码:

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

仔细观察,不难发现:

  • 递归边界:n==0
  • 递归式:F(n-1)*n

来仔细的分析一下,对于F(5)来说——相当于是F(4)*5,以此类推,直接将F(5)分解到了F(0),此时F(0)=1,即子问题的答案,再将所有子问题的答案合并,即可完成本次求解~

假设输入的是3,则推倒过程依次为:

  • F(3)
  • F(2)*3
  • F(1)*2*3
  • F(0)*1*2*3
  • 得到最后的F(0)的值以后,再返回去依次计算F(1)、F(2)、F(3)

四.递归计算裴波那契数列

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

仔细观察,也没什么难度:

  • 递归边界:0和1的返回值均为1
  • 递归式:根据定义,第三项开始即为前两项的和

        对于这类递归问题,只要找到了递归边界和递归式,写起来代码就没什么难度。递归边界用来返回最简单底层的结果,递归式用来减小规模并进一步向下一层递归。递归图可以将递归放在一个平面上思考,有利于更快分析题目~

五.全排列

        某种意义上来说,学会递归的思维正是从一个只会暴力的小白蜕变的过程,比如当我们要求输入1~n之间数的全排列,如果硬碰硬直接霸王硬上弓,这个复杂度简直不能想象——毕竟光数量都达到n的阶乘个,何况找起来也是很费事的。

        从递归的角度去考虑,如果把问题描述成“1~n这n个整数的全排列”,那么就可以拆分为若干个子问题:“输出以1开头的全排列”、“输出以2开头的全排列”……以此类推。不妨设置一个数组P,用来存放当前的排列;再设置一个散列数组hashTable,其中hashTable[x]当x已在P中时赋值为true。

        现在按照顺序往P中的第1位到第N位填入数字。不妨假设当前已经填好了1~index-1位,正准备去填写index位。我们需要枚举1~n,如果当前枚举的数字x还没哟再1~index-1中,即填入到index位,同时设置hashTable[x]为true,然后去处理index+1位;如果递归完成时,以便让P[index]填写下一个数字。

#include <cstdio>
#include <iostream> 
using namespace std;
const int maxn=11;int n,P[11],hashTable[maxn]={false};
//p为当前排列
//hashTable用来记录x是否已经在P中! void generateP(int index)  //当前处理的正是第index位 
{if(index==n+1) //1~n已经处理完了,所以相当于n+1为递归边界~ {for(int i=1;i<=n;i++)cout<<P[i];  //输出当前排列 cout<<endl;return;}for(int x=1;x<=n;x++)   //枚举1~n,试图将x填入到P[index]位上! {if(hashTable[x]==false)   //false即表示不存在~ {P[index]=x;   //填入到index位 hashTable[x]=true;  generateP(index+1);  //递归处理下一位:即index+1 hashTable[x]=false;}}
}int main() {n=3;generateP(1);return 0; 
}
  • 递归边界:index==n+1
  • 递归式:generateP(index+1);

六.N皇后问题

        N 皇后问题指的是如何将 N 个皇后放置在 N × N 的棋盘上,并且使皇后彼此之间不能相互攻击。即给你一个整数 N ,返回所有不同的 N 皇后问题的解决方案数量~

        这玩意,不知道大家有没有想起来行列式的定义:将行列式视为从矩阵的不同行和不同列中选取元素并相乘的代数和。每一项的符号由列标的逆序数决定,即如果列标的逆序数为奇数,则该项为负;若为偶数,则该项为正——其实就是全排列~不过不同的是,行列式可以在对角线上选择元素,而对于可以斜线行走的皇后,这一点显然也是不行。因此可以基于全排列的代码,然后对每一个全排列的结果进行单独判断是否存在对角线元素,即可完成~ 

 如下:判断是否在同一对角线,只需要看行距之差和列距之差的绝对值是否相同,即可:

int count=0;
void generateP(int index)  //当前处理的正是第index位 
{if(index==n+1) //1~n已经处理完了,所以相当于n+1为递归边界~ {bool flag=true;  //flag为true时表示当前为一个合法方案~ for(int i=1;i<=n;i++){for(int j=1;j<=n;j++)if(abs(i-j)==abs(P[i]-P[j])) flag=false;   //不合法 	}if(flag)count++;return;}for(int x=1;x<=n;x++)   //枚举1~n,试图将x填入到P[index]位上! {if(hashTable[x]==false)   //false即表示不存在~ {P[index]=x;   //填入到index位 hashTable[x]=true;  generateP(index+1);  //递归处理下一位:即index+1 hashTable[x]=false;}}
}

对于递归,只要想清楚边界、递归式、问题需要的答案,就没什么难度~

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[氮化镓]Kevin J. Chen组新作—肖特基p-GaN HEMTs正栅ESD机理研究

这篇文章是发表在《IEEE Electron Device Letters》上的一篇关于Schottky型p-GaN栅极高电子迁移率晶体管&#xff08;HEMTs&#xff09;的正向栅极静电放电&#xff08;ESD&#xff09;机理研究的论文。文章由Jiahui Sun等人撰写&#xff0c;使用了基于碳化硅&#xff08;SiC&a…

Java--多态

1.多态为同一方法根据发送对象的不同而采用多种不同的行为方式 2.一个对象的实际类型是确定的&#xff0c;但可以指向对象的引用的类型有很多 3.多态存在的条件 1.有继承关系 2.子类重写父类方法 3.父类引用指向子类对象 4.多态是方法的多态&#xff0c;属性没有多态 5.由于…

全网最适合入门的面向对象编程教程:11 类和对象的Python实现-子类调用父类方法-模拟串口传感器和主机

全网最适合入门的面向对象编程教程&#xff1a;11 类和对象的 Python 实现-子类调用父类方法-模拟串口传感器和主机 摘要&#xff1a; 本节课&#xff0c;我们主要讲解了在 Python 类的继承中子类如何进行初始化、调用父类的属性和方法&#xff0c;同时讲解了模拟串口传感器和…

Python | Leetcode Python题解之第223题矩形面积

题目&#xff1a; 题解&#xff1a; class Solution:def computeArea(self, ax1: int, ay1: int, ax2: int, ay2: int, bx1: int, by1: int, bx2: int, by2: int) -> int:area1 (ax2 - ax1) * (ay2 - ay1)area2 (bx2 - bx1) * (by2 - by1)overlapWidth min(ax2, bx2) - …

电动卡丁车语音芯片方案选型:让驾驶体验更智能、更安全

在追求速度与激情的电动卡丁车领域&#xff0c;每一次升级都意味着更加极致的驾驶体验。而今天&#xff0c;我们要介绍的&#xff0c;正是一款能够显著提升电动卡丁车智能化与安全性的语音芯片方案——为您的爱车增添一份独特的魅力与安全保障。 智能化升级&#xff0c;从“听…

【js面试题】js的数据结构

面试题&#xff1a;说说你了解的js数据结构 JavaScript中的数据结构是编程的基础&#xff0c;它们帮助我们以高效的方式存储和操作数据。 下面将详细介绍 这些数据结构的来源、概念和应用场景。 数组 Array 来源&#xff1a; 数组是一种线性数据结构&#xff0c;起源于计算…

卷积神经网络可视化的探索

文章目录 训练LeNet模型下载FashionMNIST数据训练保存模型 卷积神经网络可视化加载模型一个测试图像不同层对图像处理的可视化第一个卷积层的处理第二个卷积层的处理 卷积神经网络是利用图像空间结构的一种深度学习网络架构&#xff0c;图像在经过卷积层、激活层、池化层、全连…

PyJWT,一个基于JSON的轻量级安全通信方式的python库

目录 什么是JWT&#xff1f; JWT的构成 PyJWT库简介 安装PyJWT 生成JWT 验证JWT 使用PyJWT的高级功能 自定义Claims 错误处理 结语 什么是JWT&#xff1f; 在介绍PyJWT这个Python库之前&#xff0c;我们首先需要了解什么是JWT。JWT&#xff0c;全称JSON Web Token&am…

Java根据经纬度获取两点之间的距离

Java根据经纬度获取两点之间的距离&#xff0c;最近在实现类似于钉钉打卡签到的需求&#xff0c;因为对精度要求不是很高&#xff0c;所以可以通过一个球面距离的公式来求两点距离&#xff0c;这里将地球当成一个球体&#xff0c;实际上地球是一个不规则的球体&#xff0c;所以…

HttpServer内存马

HttpServer内存马 基础知识 一些基础的方法和类 HttpServer&#xff1a;HttpServer主要是通过带参的create方法来创建&#xff0c;第一个参数InetSocketAddress表示绑定的ip地址和端口号。第二个参数为int类型&#xff0c;表示允许排队的最大TCP连接数&#xff0c;如果该值小…

Xilinx FPGA DDR4 接口的 PCB 准则

目录 1. 简介 1.1 FPGA-MIG 与 DDR4 介绍 1.2 DDR4 信号介绍 1.2.1 Clock Signals 1.2.2 Address and Command Signals 1.2.3 Address and Command Signals 1.2.4 Data Signals 1.2.5 Other Signals 2. 通用存储器布线准则 3. Xilinx FPGA-MIG 的 PCB 准则 3.1 引脚…

【Excel】 批量跳转图片

目录标题 1. CtrlA全选图片 → 右键 → 大小和属性2. 取消 锁定纵横比 → 跳转高度宽度 → 关闭窗口3. 最后一图拉到最后一单元格 → Alt吸附边框![](https://i-blog.csdnimg.cn/direct/d56ac1f41af54d54bb8c68339b558dd1.png)4. CtrlA全选图片 → 对齐 → 左对齐 → 纵向分布!…

uniapp实现一个键盘功能

前言 因为公司需要&#xff0c;所以我.... 演示 代码 键盘组件代码 <template><view class"keyboard_container"><view class"li" v-for"(item, index) in arr" :key"index" click"changArr(item)" :sty…

Linux的前世今生

Unix的起源和发展 1969年&#xff0c;AT&T贝尔实验室的Ken Thompson和Dennis Ritchie等人开发了Unix操作系统。Unix的设计理念强调小而简洁的工具&#xff0c;文本流和系统模块化&#xff0c;这些理念后来成为Linux开发的重要基础。1973年&#xff0c;Unix用C语言重新编写…

收银系统源码-营销活动-幸运抽奖

1. 功能描述 营运抽奖&#xff1a;智慧新零售收银系统&#xff0c;线上商城营销插件&#xff0c;商户/门店在小程序商城上设置抽奖活动&#xff0c;中奖人员可内定&#xff1b; 2.适用场景 新店开业、门店周年庆、节假日等特定时间促销&#xff1b;会员拉新&#xff0c;需会…

DDR3 (四)

1 DDR3 8倍预取 DDR3相比DDR2外部IO时钟又提高了一倍&#xff0c;因此DDR3外部IO时钟是内核时钟的4倍&#xff0c;再加上双沿采样&#xff0c;因此DDR3可以实现8倍预取 2 DDR3 芯片位宽 DDR3使用8倍预取技术&#xff0c;指的是芯片位宽&#xff08;DQ数据线位宽&#xff09…

逻辑回归模型(非回归问题,而是分类问题)

目录&#xff1a; 一、Sigmoid函数&#xff1a;二、逻辑回归介绍&#xff1a;三、决策边界四、逻辑回归模型训练过程&#xff1a;1.训练目标&#xff1a;2.梯度下降调整参数&#xff1a; 一、Sigmoid函数&#xff1a; Sigmoid函数是构建逻辑回归模型的重要函数&#xff0c;如下…

探展2024世界人工智能大会之令人惊艳的扫描黑科技~

文章目录 ⭐️ 前言⭐️ AIGC古籍修复文化遗产焕新⭐️ 高效的文档图像处理解决方案⭐️ AIGC扫描黑科技一键全搞定⭐️ 行业级的知识库大模型加速器⭐️ 结语 ⭐️ 前言 大家好&#xff0c;我是 哈哥&#xff08;哈哥撩编程&#xff09;&#xff0c;这次非常荣幸受邀作为专业…

Linux中的粘滞位及mysql日期函数

只要用户具有目录的写权限, 用户就可以删除目录中的文件, 而不论这个用户是否有这个文件的写 权限. 为了解决这个不科学的问题, Linux引入了粘滞位的概念. 粘滞位 当一个目录被设置为"粘滞位"(用chmod t),则该目录下的文件只能由 一、超级管理员删除 二、该目录…

回归损失和分类损失

回归损失和分类损失是机器学习模型训练过程中常用的两类损失函数&#xff0c;分别适用于回归任务和分类任务。 回归损失函数 回归任务的目标是预测一个连续值&#xff0c;因此回归损失函数衡量预测值与真实值之间的差异。常见的回归损失函数有&#xff1a; 均方误差&#xff…