递归学习第一个课

news2024/11/16 13:32:41


一、递归定义

基本定义

  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.coloradmin.cn/o/1575052.html

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

相关文章

LeetCode 热题 100 | 动态规划(一)

目录 1 70. 爬楼梯 1.1 基本思路 1.2 官方题解 2 118. 杨辉三角 3 198. 打家劫舍 菜鸟做题&#xff0c;语言是 C 1 70. 爬楼梯 核心思想&#xff1a;把总问题拆解为若干子问题。 总问题&#xff1a;上到 5 楼的方式有多少种子问题&#xff1a;上到 4 楼的方式有多…

k8s安全控制、授权管理介绍,全网最新

3.ABAC 4.Webhook 5.Node 6.RBAC 三.Role解释 1.Role和ClusterRole 2.Rolebinding和ClusterBinding 3.Rolebinding和ClusterRole 四.准入控制 1.命令格式 2.可配置控制器 五.例子 1.生成签署证书 2.设置用户和上下文信息 3.为sulibao用户授权 一.Kubernetes安全控…

4.7学习总结

java学习 一.Stream流 (一.)概念: Stream将要处理的元素集合看作一种流&#xff0c;在流的过程中&#xff0c;借助Stream API对流中的元素进行操作&#xff0c;比如&#xff1a;筛选、排序、聚合等。Stream流是对集合&#xff08;Collection&#xff09;对象功能的增强&…

如何使用Java和RabbitMQ实现延迟队列?

前言 今天我们使用Java和RabbitMQ实现消息队列的延迟功能。 前期准备&#xff0c;需要安装好docker、docker-compose的运行环境。 需要安装RabbitMQ的可以看下面这篇文章。 如何使用PHP和RabbitMQ实现消息队列&#xff1f;-CSDN博客 今天讲的是依赖RabbitMQ的延迟插件实现…

优秀企业都在用的企微知识库,再不搭建就晚了!

每个团队都在寻找让工作效率提升的方法。如果你想知道哪些团队能够高效地完成任务&#xff0c;而另一些却步履维艰&#xff0c;那么答案可能就是“企业微信知识库”。见过很多团队都在使用它&#xff0c;而且效果非常显著。如果你还没有搭建属于自己的企微知识库&#xff0c;可…

【活动创作】未来AI技术方面会有哪些创业机会

放假期间突然看到这个活动创作&#xff0c;觉得很有意思&#xff0c;既然如此&#xff0c;我就先让AI来回答一下吧&#xff0c;哈哈 1、文心一言 首先来看看文心一言的回答&#xff1a; 2、讯飞星火 然后来看看讯飞星火的回答&#xff1a; 3、个人感受 最后来说说给人感受吧&am…

基于springboot+vue的医院信息管理系统(附源码+视频介绍) 前后端分类

一、项目背景介绍&#xff1a; 医院管理系统从整个社会实践过程来看&#xff0c;对医院进行信息化管理可以带来的好处如下所示&#xff1a; &#xff08;1&#xff09;患者快速预约就诊。不同于线下就诊的是&#xff0c;患者不需要到医院进行排队叫号,然后才能正常就诊&#x…

【STL学习】(4)vector的模拟

前言 本文将模拟实现vector的常用功能&#xff0c;目的在于更深入理解vector。 一、前置知识 在模拟之前先对vector的结构和常用接口学习&#xff0c;有一个大致了解。看源码&#xff0c;本文参考的源码是SGI版本的stl3.0。 技巧&#xff1a; 看源码不要一行一行的看&#xff…

软件测试常考面试题-软件测试面试宝典(一篇足矣)

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

【系统架构师】-软件架构设计

1、软件架构的概念 架构的本质 1、软件架构为软件系统提供了一个结构、行为和属性的高级抽象。 2、软件架构风格是特定应用领域的惯用模式&#xff0c;架构定义一个词汇表和一组约束。 架构的作用 1、软件架构是项目干系人进行交流的手段。 2、软件架构是可传递和可复用的模型…

creo扫描杯子学习笔记

creo扫描杯子学习笔记 扫描2要素&#xff1a; 轨迹&#xff0c; 截面。 多用于曲线扫描&#xff0c;区别于拉伸命令。 大小自定 旋转扫描 抽壳 草绘把手 扫描把手 复制曲面 实例化切除 成型

Leetcode 148. 排序链表

心路历程&#xff1a; 这道题通过很简单&#xff0c;但是如果想要用O(1)的空间复杂度O(nlogn)的时间复杂度的话&#xff0c;可能得需要双指针快排的思路。 解法&#xff1a;遍历模拟 # Definition for singly-linked list. # class ListNode: # def __init__(self, val0…

容器和K8s常见概念

【容器】 1、Open Container Initiative&#xff08;OCI&#xff09;&#xff1a;制定和推动容器格式和运行时的开放标准。容器运行时需要遵循此标准。主要的产出物包括&#xff1a; OCI Image Specification: 定义容器镜像格式的规范&#xff0c;统一描述容器镜像的内容和结…

软考高级架构师:嵌入式系统的内核架构

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

【C++进阶】哈希思想之哈希表和哈希桶模拟实现unordered_map和unordered_set

哈希表和哈希桶 一&#xff0c;什么是哈希二&#xff0c;关联式容器unordered_map/set1. unordered_map2. unordered_set 三&#xff0c;哈希的结构1. 哈希函数2. 哈希冲突 四&#xff0c;哈希表&#xff08;闭散列&#xff09;及其模拟实现五&#xff0c;哈希桶&#xff08;开…

Android JNI调试总结

1、确保NDK和CMake已经安装 新建能编译APK的工程&#xff0c;工程中添加相关ndk目录 2、添加C模块 添加完成后&#xff0c;工程目录自动更新&#xff0c;build.gradle导入了so编译器 修改build.gradle中添加相关gcc编译器如下 externalNativeBuild { cmake { abiFilters a…

零信任安全模型:构建未来数字世界的安全基石

在数字化转型的浪潮中&#xff0c;云原生技术已成为推动企业创新和灵活性的关键力量&#x1f4a1;。然而&#xff0c;随着技术的进步和应用的广泛&#xff0c;网络安全威胁也日益严峻&#x1f513;&#xff0c;传统的网络安全模型已经难以应对复杂多变的网络环境。在这样的背景…

webpack环境配置分类结合vue使用

文件目录结构 按照目录结构创建好文件 控制台执行: npm install /config/webpack.common.jsconst path require(path) const {merge} require(webpack-merge) const {CleanWebpackPlugin} require(clean-webpack-plugin) const { VueLoaderPlugin } require(vue-loader); c…

Spring Security——11,自定义权限校验方法

自定义权限校验方法 一键三连有没有捏~~ 我们也可以定义自己的权限校验方法&#xff0c;在PreAuthorize注解中使用我们的方法。 自定义一个权限检验方法&#xff1a; 在SPEL表达式中使用 ex相当于获取容器中bean的名字未ex的对象。然后再调用这个对象的 hasAuthority方法&am…

中文地址分词器源码阅读(jiedi)

文章目录 structure.p文件pd.read_excelenumerate思维导图核心源码讲解jiedi.pytrain.py 总结 structure 点击左边的Structure按钮就如Structure界面。从Structure我们可以看出当前代码文件中有多少个全局变量、函数、类以及类中有多少个成员变量和成员函数。 其中V图标表示全…