当前位置: 首页 > news >正文

递归与分治算法(1)--经典递归、分治问题

目录

一、递归问题

1、斐波那契数列

2、汉诺塔问题

3、全排列问题

4、整数划分问题

二、递归式求解

1、代入法

2、递归树法

3、主定理法

三、 分治问题

1、二分搜索

2、大整数乘法


一、递归问题

1、斐波那契数列

        斐波那契数列不用过多介绍,斐波那契提出的繁殖兔子问题。

        斐波那契递推式如下:

F(n)=\begin{Bmatrix} 1\qquad \qquad \qquad \qquad \quad \ n=0\\ 1 \qquad \qquad \qquad \qquad \quad \ n=1\\ F(n-1)+F(n-2) \quad n>1 \end{Bmatrix} 

        斐波那契代码:

//斐波那契数列
import java.util.Scanner;
public class Fibonacci {public static void main(String [] args){int input=new Scanner(System.in).nextInt();System.out.println(factorial(input));}public static int factorial(int n){if(n==0||n==1)return 1;else{return factorial(n-1)+factorial(n-2);}}
}

2、汉诺塔问题

        汉诺塔问题,也是一个经典问题。一般分为三个步骤:

(1)把n-1个盘子从A柱移到B柱

(2)把最底层1个盘子从A柱移到C柱

(3)把B柱n-1个盘子移到C柱。

        完整代码: 

package RecursionAndDivide;
import java.util.Scanner;
public class Hanoi {public static void main(String[] args){int input=new Scanner(System.in).nextInt();move(input,'A','B','C');} public static void move(int n,char a,char b,char c){if(n==1)System.out.println(a+"->"+c);   //else {move(n-1,a,c,b);    //n-1个从a移到bmove(1,a,b,c);      //底层1个从a移到cmove(n-1,b,a,c);    //n-1个从b移到c}}
}

3、全排列问题

        使用递归的方式输出数组中的全排列,步骤如下:

(0)判定是否数组中仅有一个数,那么输出该排列形式。(请注意,k作为固定头,在每一层进行修改排列顺序的头部)

(1)首先将第一个数与后面的每一个数进行交换(这是一个k到m的循环)。得到:

        1,2,3,4,...,n

        2,1,3,4,...,n

        3,1,2,4,...,n

(2)计算除第一个数以外后面的全排列。

(3)交换第一个数与刚刚那个数,使数组恢复。

        k作为固定头,m作为尾,一直不改变,i作为固定头与循环中交换的数的索引。固定头依赖于第几层递归,不同的递归只会改变数组排列的方式,不会改变长度,而尾不动,所以每次输出只需要输出0到m索引的数组数,也就是所有数组的数。

完整代码:

//全排列问题
public class Permutations {public static void main(String [] args){int []list={1,2,3,4,5};int k=0;int m=list.length-1;Perm(list,k,m);} //产生全排列public static void Perm(int []list,int k,int m){if(k==m)      {for(int i=0;i<=m;i++)System.out.print(list[i]);System.out.println();}else{for(int i=k;i<=m;i++){swap(list,i,k);        Perm(list,k+1,m);swap(list,i,k);}}}//交换数组中两个元素public static void swap(int []list,int i,int k){int temp=list[i];list[i]=list[k];list[k]=temp;}
}

4、整数划分问题

        整数划分问题就是把一个正整数拆分成若干个正整数相加的所有方式,也可以使用递归来求解。定义p(n)为正整数n的划分总个数,q(n,m)为正整数n划分为最大值为m的划分总个数。

        有以下递归式成立:

q(n,m)=\begin{Bmatrix} 1 \qquad \quad \qquad \qquad \qquad \qquad n=1,m=1 \\ q(n,n) \qquad \qquad \qquad \qquad \qquad \quad n<m\\ 1+q(n,n-1) \quad \qquad \qquad \ \ \qquad n=m\\ q(n,m-1)+q(n-m,m) \quad n>m>1 \end{Bmatrix}

        完整代码: 

public class IntegerDivide {public static void main(String[] args){System.out.println(q(6,6));}public static int q(int n, int m){if((n==1)||(m==1))   //且和或一样,或的话出现q(1,2)会执行条件2,返回q(1,1)return 1;if(n<m)return q(n,n);if(n==m)return 1+q(n,n-1);return q(n,m-1)+q(n-m,m);} 
}

二、递归式求解

1、代入法

        一般来说如果递归式成倍数下降,可以n取指数形式,平衡递归式的麻烦。换元求解就是不断回带递归式,最后得到T(1)项忽略,其他换元回变量n的项。

2、递归树法

        递归树法就是将常数项逐层展开成树叶子结点的形式,并将每一层的量相加的总和为递归式的解。如下面这个题,根节点就是递归式中的常数项n-1,每一层叶子点个数就是子递推式的系数为2,叶子结点的量只用n/2换元上一节点的量,得到n/2-1,以此类推,那么递推树如下。

         计算递推式每一层的和,注意最后一层以1为结束,当使用n=2^k替代时,请注意层数变化,最后一层是\frac{n}{2^{k-1}}-1=\frac{2^k}{2^{k-1}}-1=1。那么总和如下,记得要用n替换k:

        对于这一类递归树有偏重的题,可以参照下面这个做法,找到最慢下去的叶节点路线,就是大O的复杂度。

3、主定理法

        主定理方法有一定局限性,最没有局限性的是代入法,但是很麻烦。

三、 分治问题

1、二分搜索

        二分搜索原理:

(1)初始数组是已经排好序的,目的是某个数值是否存在,并找到他的索引,否则返回-1。

(2)大循环满足左值小于等于右值,每次取中间值,判断中间值是否为给定数值,若是返回索引。

(3)判断是否小于中间值,若是右值等于mid-1,判断是否大于中间值,若是左值等于mid+1。

(4)如果不满足循环条件,还没有找到给定值,那么返回-1。

        二分搜索算法的复杂度为O(logn),应该建立在已排好序的数组上,如果为了搜索而去排序,复杂度就大大提升了。

//二分搜索
public static int Search(int arr[],int x,int n){int left=0;int right=n-1;while(left<=right){int mid=(left+right)/2;if(x==arr[mid])return mid;if(x>arr[mid])left=mid+1;else right=mid-1;}return -1;} 

2、大整数乘法

        由于大整数本身就会出现精度丢失问题,另外乘积数过大也会出现数值溢出的问题。所以可以用数组存储大整数进行两个数组之间的乘法。

        另外高复杂度O(mn)也是不能忽视的问题,可以通过大整数拆成两段,将中间二次计算的环节存入内存,来减少复杂度。

        比如下图X和Y都为n为二进制整数,计算它们的乘积,可以拆分成两个相等的n/2位的结构。

        XY=(A*2^{n/2}+B)(C*2^{n/2}+D)=AC*2^n+(AD+BC)*2^{n/2}+BD\\ XY=AC*2^n+((A-B)(D-C)+AC+BD)*2^{n/2}+BD 

        根据上面的式子改变,BD这一项就重复计算了,乘法计算的次数整体不变,但是BD可以不用二次计算了,这样就可以减少一次乘法计算,6次乘法变为5次乘法。 复杂度相比于O(n^2)也有所降低。

        相类似的,矩阵乘法也可以用这种方式降低时间复杂度,成为Strassen矩阵乘法。

 

相关文章:

递归与分治算法(1)--经典递归、分治问题

目录 一、递归问题 1、斐波那契数列 2、汉诺塔问题 3、全排列问题 4、整数划分问题 二、递归式求解 1、代入法 2、递归树法 3、主定理法 三、 分治问题 1、二分搜索 2、大整数乘法 一、递归问题 1、斐波那契数列 斐波那契数列不用过多介绍&#xff0c;斐波那契提出…...

Java之SpringCloud Alibaba【六】【Alibaba微服务分布式事务组件—Seata】

一、事务简介 事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。 在关系数据库中&#xff0c;一个事务由一组SQL语句组成。 事务应该具有4个属性: 原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性。 原子性(atomicity) ∶个事务…...

Android逆向学习(五)app进行动态调试

Android逆向学习&#xff08;五&#xff09;app进行动态调试 一、写在前面 非常抱歉鸽了那么久&#xff0c;前一段时间一直在忙&#xff0c;现在终于结束了&#xff0c;可以继续更新android逆向系列的&#xff0c;这个系列我会尽力做下去&#xff0c;然后如果可以的话我看看能…...

音频编辑软件Steinberg SpectraLayers Pro mac中文软件介绍

Steinberg SpectraLayers Pro mac是一款专业的音频编辑软件&#xff0c;旨在帮助音频专业人士进行精细的音频编辑和声音处理。它提供了强大的频谱编辑功能&#xff0c;可以对音频文件进行深入的频谱分析和编辑。 Steinberg SpectraLayers Pro mac软件特点 1. 频谱编辑&#xff…...

基于.Net Core实现自定义皮肤WidForm窗口

前言 今天一起来实现基于.Net Core、Windows Form实现自定义窗口皮肤&#xff0c;并实现窗口移动功能。 素材 准备素材&#xff1a;边框、标题栏、关闭按钮图标。 窗体设计 1、创建Window窗体项目 2、窗体设计 拖拉4个Panel控件&#xff0c;分别用于&#xff1a;标题栏、关…...

【Rust】操作日期与时间

目录 介绍 一、计算耗时 二、时间加减法 三、时区转换 四、年月日时分秒 五、时间格式化 介绍 Rust的时间操作主要用到chrono库&#xff0c;接下来我将简单选一些常用的操作进行介绍&#xff0c;如果想了解更多细节&#xff0c;请查看官方文档。 官方文档&#xff1a;chr…...

blender快捷键

1&#xff0c; shift a 添加物体 2&#xff0c;ctrl alt q 切换四格视图 3, ~ 展示物体的各个视图按钮&#xff0c;&#xff08;~ 就是tab键上面的键&#xff09; 4&#xff0c;a 全选&#xff0c;全选后&#xff0c;点 ctrl 鼠标框选 减去已经选择的&#xff1b…...

java Spring Boot 自动启动热部署 (别再改点东西就要重启啦)

上文 java Spring Boot 手动启动热部署 我们实现了一个手动热部署的代码 但其实很多人会觉得 这叫说明热开发呀 这么捞 写完还要手动去点一下 很不友好 其实我们开发人员肯定是希望重启这种事不需要自己手动去做 那么 当然可以 我们就让它自己去做 Build Project 这个操作 我们…...

TouchGFX之后端通信

在大多数应用中&#xff0c;UI需以某种方式连接到系统的其余部分&#xff0c;并发送和接收数据。 它可能会与硬件外设&#xff08;传感器数据、模数转换和串行通信等&#xff09;或其他软件模块进行交互通讯。 Model类​ 所有TouchGFX应用都有Model类&#xff0c;Model类除了存…...

cesium gltf控制

gltf格式详解 glTF格式本质上是一个JSON文件。这一文件描述了整个3D场景的内容。它包含了对场景结构进行描述的场景图。场景中的3D对象通过场景结点引用网格进行定义。材质定义了3D对象的外观,动画定义了3D对象的变换操作(比如选择、平移操作)。蒙皮定义了3D对象如何进行骨骼…...

Spring的依赖注入(DI)以及优缺点

Spring的依赖注入&#xff08;DI&#xff09;&#xff1a;解释和优点 依赖注入&#xff08;Dependency Injection&#xff0c;简称DI&#xff09;是Spring框架的核心概念之一&#xff0c;也是现代Java应用程序开发的重要组成部分。本文将深入探讨DI是什么&#xff0c;以及它的…...

【强化学习】05 —— 基于无模型的强化学习(Prediction)

文章目录 简介蒙特卡洛算法时序差分方法Example1 MC和TD的对比偏差&#xff08;Bias&#xff09;/方差&#xff08;Variance&#xff09;的权衡Example2 Random WalkExample3 AB 反向传播(backup)Monte-Carlo BackupTemporal-Difference BackupDynamic Programming Backup Boot…...

【计算机组成原理】考研真题攻克与重点知识点剖析 - 第 1 篇:计算机系统概述

前言 本文基础知识部分来自于b站&#xff1a;分享笔记的好人儿的思维导图&#xff0c;感谢大佬的开源精神&#xff0c;习题来自老师划的重点以及考研真题。此前我尝试了完全使用Python或是结合大语言模型对考研真题进行数据清洗与可视化分析&#xff0c;本人技术有限&#xff…...

【Java-LangChain:面向开发者的提示工程-8】聊天机器人

第八章 聊天机器人 使用一个大型语言模型的一个令人兴奋的事情是&#xff0c;我们可以用它来构建一个定制的聊天机器人 (Chatbot) &#xff0c;只需要很少的工作量。在这一节中&#xff0c;我们将探索如何利用聊天的方式&#xff0c;与个性化&#xff08;或专门针对特定任务或…...

利用t.ppft.interval分别计算T分布置信区间[实例]

scipy.stats.t.interval用于计算t分布的置信区间&#xff0c;即给定置信水平时&#xff0c;计算对应的置信区间的下限和上限。 scipy.stats.t.ppf用于计算t分布的百分位点&#xff0c;即给定百分位数&#xff08;概率&#xff09;时&#xff0c;该函数返回给定百分位数对应的t…...

软件工程第三周

可行性研究 续 表达工作量的方式 LOC估算&#xff1a;Line of Code 估算公式S(Sopt4SmSpess)/6 FP&#xff1a;功能点 1. LOC (Line of Code) 估算 定义&#xff1a;LOC是指一个软件项目中的代码行数。 2. FP (Function Points) 估算 定义&#xff1a;FP是基于软件的功能性和…...

动态链接那些事

1、为什么要动态链接 1.1 空间浪费 对于静态链接来说&#xff0c;在程序运行之前&#xff0c;会将程序所需的所有模块编译、链接成一个可执行文件。这种情况下&#xff0c;如果 Program1 和 Program2 都需要用到 Lib.o 模块&#xff0c;那么&#xff0c;内存中和磁盘中实际上就…...

力扣:118. 杨辉三角(Python3)

题目&#xff1a; 给定一个非负整数 numRows&#xff0c;生成「杨辉三角」的前 numRows 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官…...

QGIS文章二——DEM高程裁剪和3D地形图

经常看到别人基于高程文件制作出精美的3D地图&#xff0c;笔者按照互联网几种制作方式进行尝试后&#xff0c;写的DEM高程裁剪和3D地形图教程&#xff0c;或许其中有一些错误的&#xff0c;也请指出。 本文基于海南省的shp文件和海南省DEM高程文件&#xff0c;制作海口地区的3D…...

【kubernetes】kubernetes中的StatefulSet使用

TOC 1 为什么需要StatefulSet 常规的应用通常使用Deployment&#xff0c;如果需要在所有机器上部署则使用DaemonSet&#xff0c;但是有这样一类应用&#xff0c;它们在运行时需要存储一些数据&#xff0c;并且当Pod在其它节点上重建时也希望这些数据能够在重建后的Pod上获取&…...

OpenClaw成本优化方案:nanobot轻量镜像替代高价API实测

OpenClaw成本优化方案&#xff1a;nanobot轻量镜像替代高价API实测 1. 为什么需要关注OpenClaw的成本问题 去年冬天&#xff0c;当我第一次用OpenClaw完成邮件自动回复的完整流程时&#xff0c;既兴奋又心疼。兴奋的是它真的能像人类一样读取邮件、分析内容、生成回复&#x…...

基于AI多因子与流动性模型的黄金再定价分析:4500关口修复后的“黄金坑”是否成立?

摘要&#xff1a;本文通过引入AI多因子定价模型&#xff0c;结合流动性压力识别算法、资金流向追踪系统与宏观变量建模&#xff0c;对黄金从5602美元回落至4099美元后的市场行为进行分析&#xff0c;重点解析抛售驱动逻辑、相关性漂移及4500美元关口的再定价机制。一、AI趋势重…...

从‘噬菌体’到清晰地图:我的LIO-SAM避坑实战记录(含Ubuntu版本选择建议)

从“噬菌体”到清晰地图&#xff1a;LIO-SAM实战避坑指南与Ubuntu版本选择建议 第一次在RViz里看到那个旋转成筒状的地图时&#xff0c;我盯着屏幕足足愣了三分钟——这和我预想中的高精度点云地图相差了十万八千里。更令人崩溃的是&#xff0c;当我把设备搬到室外测试时&#…...

告别串口线!手把手教你用WCH-LinkE的SDI功能实现CH32V303RCT6的无线调试打印

无线调试革命&#xff1a;基于WCH-LinkE的SDI功能实现CH32V303RCT6高效打印 调试嵌入式系统时&#xff0c;串口打印是最常用的调试手段之一。然而传统串口调试需要占用宝贵的硬件UART资源&#xff0c;在IO口紧张或串口已被占用的场景下尤为不便。沁恒微电子推出的SDI(Serial Da…...

Java大厂面试实战:电商高并发场景下的Spring Boot+Redis+Kafka技术栈深度解析

Java大厂面试实战&#xff1a;电商高并发场景下的技术栈深度解析 前言 在互联网大厂面试中&#xff0c;技术面试官往往会结合具体业务场景来考察候选人的技术深度和广度。本文模拟了一场电商场景下的Java技术面试&#xff0c;通过面试官与求职者"谢飞机"的三轮对话&a…...

告别Mac!在Windows电脑上用HBuilder X和Appuploader搞定iOS测试包(附7天免费证书申请)

在Windows平台实现iOS应用打包测试的全流程指南 对于Windows平台的开发者而言&#xff0c;iOS应用打包测试一直是个令人头疼的问题。传统方式需要依赖Mac电脑和复杂的Xcode工具链&#xff0c;不仅成本高昂&#xff0c;学习曲线也陡峭。但如今&#xff0c;借助HBuilder X和Appup…...

VCAM虚拟摄像头:3大创新功能解锁安卓摄像头的无限应用场景

VCAM虚拟摄像头&#xff1a;3大创新功能解锁安卓摄像头的无限应用场景 【免费下载链接】com.example.vcam 虚拟摄像头 virtual camera 项目地址: https://gitcode.com/gh_mirrors/co/com.example.vcam VCAM虚拟摄像头是一款基于Xposed框架的安卓虚拟相机解决方案&#x…...

2026年智能系统控制、优化与应用国际学术会议(ISCOA 2026)

【重要信息】 会议官网&#xff1a;https://www.yanfajia.com/action/p/2W49G66K 会议时间&#xff1a;2026年10月16-18日 会议地点&#xff1a;中国 成都 截稿日期&#xff1a;2026年6月1日&#xff08;早鸟优惠咨询&#xff09; 接收或拒收通知&#xff1a;文章投递后…...

Synology Photos CPU驱动人脸识别补丁:解锁旧设备AI相册的终极方案

Synology Photos CPU驱动人脸识别补丁&#xff1a;解锁旧设备AI相册的终极方案 【免费下载链接】Synology_Photos_Face_Patch Synology Photos Facial Recognition Patch 项目地址: https://gitcode.com/gh_mirrors/sy/Synology_Photos_Face_Patch 还在为群晖NAS无法使用…...

Vue 3 + hls.js 实战:手把手教你打造一个能‘续命’的安防监控播放器

Vue 3 hls.js 打造安防级视频流播放器的"续命"秘籍 在安防监控、智慧城市等实时视频流应用场景中&#xff0c;网络抖动、服务中断、页面切换等问题常常导致视频播放中断&#xff0c;严重影响监控效果。本文将深入探讨如何基于Vue 3和hls.js构建一个具备"续命&q…...