递归学习第一个课

本文探讨了递归的基本概念,包括递归定义、终止条件、递归关系,以及其在解决二叉搜索树、斐波那契数列、缓存优化、分治策略、回溯算法等实例中的应用。还介绍了不同类型的递归,如直接递归、间接递归、尾递归和多态递归,以及动态规划在爬楼梯问题中的应用。
摘要由CSDN通过智能技术生成


一、递归定义

基本定义

  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);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值