当前位置: 首页 > 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上获取&…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现

目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...

C++_核心编程_多态案例二-制作饮品

#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为&#xff1a;煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例&#xff0c;提供抽象制作饮品基类&#xff0c;提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

css实现圆环展示百分比,根据值动态展示所占比例

代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...

可靠性+灵活性:电力载波技术在楼宇自控中的核心价值

可靠性灵活性&#xff1a;电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中&#xff0c;电力载波技术&#xff08;PLC&#xff09;凭借其独特的优势&#xff0c;正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据&#xff0c;无需额外布…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils&#xff1a; ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类&#xff0c;封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz&#xff0c;先构建任务的 JobD…...

剑指offer20_链表中环的入口节点

链表中环的入口节点 给定一个链表&#xff0c;若其中包含环&#xff0c;则输出环的入口节点。 若其中不包含环&#xff0c;则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现

摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序&#xff0c;以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务&#xff0c;提供稳定高效的数据处理与业务逻辑支持&#xff1b;利用 uniapp 实现跨平台前…...

【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验

系列回顾&#xff1a; 在上一篇中&#xff0c;我们成功地为应用集成了数据库&#xff0c;并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了&#xff01;但是&#xff0c;如果你仔细审视那些 API&#xff0c;会发现它们还很“粗糙”&#xff1a;有…...

【决胜公务员考试】求职OMG——见面课测验1

2025最新版&#xff01;&#xff01;&#xff01;6.8截至答题&#xff0c;大家注意呀&#xff01; 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:&#xff08; B &#xff09; A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...