递归学习第一个课


一、递归定义

基本定义

  1. 函数自己调用自己(通俗第一印象)
  2. 大问题可以拆分小问题(拆分,边界)
  3. 大问题与小问题的关系(递归关系)
    1. 为什么拆分小问题?
      1. 小问题更容易求解
      2. 大问题与小问题内部结果一样
      3. 大问题与小问题入参不一样

核心概念

  1. 终止条件或边界条件
  2. 递归关系:大问题与小问题的关系

例题

  • 700. 二叉搜索树中的搜索
  • /*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode() {}*     TreeNode(int val) { this.val = val; }*     TreeNode(int val, TreeNode left, TreeNode right) {*         this.val = val;*         this.left = left;*         this.right = right;*     }* }*/
    //递归解法
    class Solution {public TreeNode searchBST(TreeNode root, int val) {if(root == null){return null;}if(root.val == val){return root;}if(val<root.val){return searchBST(root.left,val);}else{return searchBST(root.right,val);}}
    }//迭代替换递归解法
    class Solution {public TreeNode searchBST(TreeNode root, int val) {while (root != null) {if (root.val == val) {return root;}if (val < root.val) {root = root.left;} else {root = root.right;}}return null;}
    }

二、递归思想分类

1、缓存

  1. 将计算结果缓存,避免重复计算
  2. 使用cache缓存存答案,key就是参数,value就是答案

例题

  • leedCode 509 斐波那契数列
    • //解法1:普通递归写法
      class Solution {public int fib(int n) {if(n == 0){return 0;}if( n == 1){return 1;}return fib(n-1) + fib(n-2);}
      }//解法2:通过缓存减少重复计算
      class Solution {Map<Integer,Integer> cache=new HashMap<>();public int fib(int n) {if(cache.get(n) != null){return cache.get(n);}if(n == 0){return 0;}if( n == 1){return 1;}int ans = fib(n-1) + fib(n-2);cache.put(n,ans);return ans;}
      }//解法3:通过迭代替换递归
      //类似双指针,pre,next每次都从左往右移动,没移动一次就做一次计算下一个数的动作。边界是n<2
      class Solution {public int fib(int n) {if( n < 2){return n;}int pre = 0,next = 0,ans = 1;for(int i = 2 ;i<=n ; i++){pre = next;next = ans;ans = pre + next;}return ans;}
      }

    • 70. 爬楼梯 (青蛙跳台阶)
      • //直接用户递归求解会超时,必须用cache缓存所有答案
        class Solution {Map<Integer,Integer> cache=new HashMap<>();public int climbStairs(int n) {if(cache.get(n) != null){return cache.get(n);}if( n == 0 ){return 1;}if( n == 1 ){return 1;}if( n == 2 ){return 2;}int ans = climbStairs(n-1) + climbStairs(n-2);cache.put(n,ans);return ans;}
        }

  • //动态规划求解,没看懂
    class Solution {public int climbStairs(int n) {int a = 1, b = 1, sum;for(int i = 0; i < n - 1; i++){sum = a + b;a = b;b = sum;}return b;}
    }
    

2、分治

  1. 将一个大问题拆分成小问题,各个击破,然后将小问题的解组合起来
  2. 几乎等价标准的递归,唯一的区别就是将小问题的解组合起来

例题

  • leedCode 98

3、回溯

  1. 找到所有满足某些条件的结果,不断试错,知错就改(并且问题可以用递归实现)
  2. 类似暴力搜索,但是比暴力搜索更高效(因为知错就改)

例题

  •     leedCode 22

三、递归形式的分类

直接递归(Direct Recursion)

在直接递归中,函数在其定义中直接调用自身。这是最基本和常见的形式

// 计算阶乘的直接递归示例
public class Main {public static int factorial(int n) {if (n == 0) {return 1;} else {return n * factorial(n - 1);}}public static void main(String[] args) {int result = factorial(5);System.out.println("Factorial of 5 is: " + result);}
}

间接递归(Indirect Recursion)

 在间接递归中,函数不直接调用自身,而是通过调用其他函数间接地调用自身。这种形式下,可能形成一个递归调用链。

// 间接递归示例:偶数和奇数的判断
public class Main {public static boolean isEven(int n) {if (n == 0) {return true;} else {return isOdd(n - 1);}}public static boolean isOdd(int n) {if (n == 0) {return false;} else {return isEven(n - 1);}}public static void main(String[] args) {System.out.println("Is 6 even? " + isEven(6));System.out.println("Is 7 odd? " + isOdd(7));}
}

尾递归(Tail Recursion)

 尾递归是指递归函数中递归调用是函数的最后一个操作。在一些编程语言和编译器中,尾递归调用可以被优化为迭代形式,从而节省内存空间。

// 尾递归示例:计算斐波那契数列
public class Main {public static int fibonacci(int n, int a, int b) {if (n == 0) {return a;} else {return fibonacci(n - 1, b, a + b);}}public static void main(String[] args) {int result = fibonacci(6, 0, 1);System.out.println("Fibonacci of 6 is: " + result);}
}
// 尾递归的迭代形式示例:计算斐波那契数列
public class Main {public static int fibonacci(int n) {if (n <= 1) {return n;}int a = 0;int b = 1;int temp;for (int i = 2; i <= n; i++) {temp = b;b = a + b;a = temp;}return b;}public static void main(String[] args) {int result = fibonacci(6);System.out.println("Fibonacci of 6 is: " + result);}
}

多态递归(Polymorphic Recursion)

 多态递归是指函数在递归调用时采用不同的参数类型,导致函数的行为因输入数据类型的不同而不同。这种形式通常用于处理具有不同结构或数据类型的问题。

// 多态递归示例:根据不同输入类型处理列表
import java.util.List;public class Main {public static void processList(Object obj) {if (obj instanceof List) {List<?> list = (List<?>) obj;for (Object item : list) {processList(item);}} else {System.out.println(obj);}}public static void main(String[] args) {List<Object> nestedList = List.of(1, List.of(2, 3), 4);processList(nestedList);}
}

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

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

相关文章

qt自定义窗口在拖动过程中出现抖动且拖动后位置看上去不对

自定义窗口拖动 引言开发环境关键性代码运行结果原因分析改进代码运行结果globalPos()globalPosition()再次修改代码运行结果区别 引言 本文旨在一个问题的记录&#xff1a;自定义窗口拖动的过程中&#xff0c;窗口不能很好的跟随鼠标移动&#xff0c;此外会出现窗口拖动时抖动…

day03 51单片机

51单片机学习 1 模块化编程 1.1 什么是模块化编程 随着我们的代码越来越复杂,我们的main.c越来越长,阅读性也越来越差。如果将来开始做项目,我们可能要同时操作好几个模块,这种情况下我们无法再把代码写到同一个文件,而是要分模块管理代码。 具体实现方法,就是将源码…

在linux服务器上安装anaconda

遇到问题&#xff1a; 在linux服务器中查看当前有哪些虚拟环境&#xff0c;conda环境用不了&#xff0c;anaconda没有安装&#xff0c;所以要在linux服务器中安装虚拟环境 解决步骤如下&#xff1a; 1.首先下载anaconda的Linux版本的安装包 方法1&#xff1a;官网下载&#…

爬虫逆向非对称加密和对称加密案例

注意&#xff01;&#xff01;&#xff01;&#xff01;某XX网站逆向实例仅作为学习案例&#xff0c;禁止其他个人以及团体做谋利用途&#xff01;&#xff01;&#xff01; 案例--aHR0cHM6Ly9jcmVkaXQuaGxqLmdvdi5jbi94eWdzL3l6d2ZzeHF5bWQv 第一步&#xff1a;分析页面、请求…

C#学习笔记9:winform上位机与西门子PLC网口通信_上篇

今日继续我的C#学习笔记&#xff0c;今日开始学习打开使用千兆网口来进行与西门子PLC的通信&#xff1a; 文章提供整体代码、解释、测试效果截图、整体测试工程下载&#xff1a; 主要包含的知识有&#xff1a;下载NuGet程序包、西门子PLC及通信协议、搭建虚拟的S7通信仿真环境…

【游戏分析】某游戏 无敌+代码

0x1 线索: 血量 1,开启DXF 2. OD附加 3. ce搜索 我们要实现无敌的思路是&#xff0c;把减去血量的逻辑给移除&#xff0c;这样就达到了无敌的效果 我们先找到血量的地址 535,改变一次血量,前面2个绿色的都是GameRpcs.dll中的地址&#xff0c;我们忽略掉。.. 这2个&#xff…

【服务器uwsgi + flask + nginx的搭建】

目录 服务器uwsgi flask nginx的搭建1. 安装必要的软件2. 启动nginx服务3. 测试Nginx4. 配置uwsgi和flask5. 配置nginx 服务器uwsgi flask nginx的搭建 1. 安装必要的软件 安装Python、uWSGI、Flask 和 Nginx。 # Ubuntu 安装命令 sudo apt-get update sudo apt-get ins…

MySQL-主从复制:概述、原理、同步数据一致性问题、搭建流程

主从复制 1. 主从复制概述 1.1 如何提升数据库并发能力 一般应用对数据库而言都是“读多写少”&#xff0c;也就说对数据库读取数据的压力比较大&#xff0c;有一个思路就是采用数据库集群的方案&#xff0c;做主从架构、进行读写分离&#xff0c;这样同样可以提升数据库的并…

【引子】C++从介绍到HelloWorld

C从介绍到HelloWorld 一、C的介绍1. 简介2. 应用场景3. C的标准![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/e3efb0f207f647729b92c0b5bcd4b330.png)4. C的运行过程 二、Visual Studio的安装1. 什么是Visual Studio2. Visual Studio的安装 三、完成HelloWorld1.…

突破编程_前端_SVG(概述)

1 什么是 SVG SVG&#xff0c;全称可缩放矢量图形&#xff08;Scalable Vector Graphics&#xff09;&#xff0c;是一种基于 XML&#xff08;可扩展标记语言&#xff09;的矢量图像格式。这种图像格式的主要特点是它描述的是矢量图形&#xff0c;而不是基于像素的位图图像。因…

RabbitMQ的交换机与队列

一、流程 首先先介绍一个简单的一个消息推送到接收的流程&#xff0c;提供一个简单的图 黄色的圈圈就是我们的消息推送服务&#xff0c;将消息推送到 中间方框里面也就是 rabbitMq的服务器&#xff0c;然后经过服务器里面的交换机、队列等各种关系&#xff08;后面会详细讲&am…

Java初始——IDEA-web的启动

Tomcat 文件夹作用 bin 启动 关闭的脚本文件 conf 配置 lib 依赖的jar包 logs 日志 temp 临时文件 webapps 存放的网站 Maven 1.在javaweb中&#xff0c;需要使用大量的jar包&#xff0c;手动导入 2.Maven 架构管理工具 核心&#xff1a;约定大于配置 必须按照规则 web idea-we…