万隆的笔记 万隆的笔记
博文索引
笔试面试
  • 在线学站

    • 菜鸟教程 (opens new window)
    • 入门教程 (opens new window)
    • Coursera (opens new window)
  • 在线文档

    • w3school (opens new window)
    • Bootstrap (opens new window)
    • Vue (opens new window)
    • 阿里开发者藏经阁 (opens new window)
  • 在线工具

    • tool 工具集 (opens new window)
    • bejson 工具集 (opens new window)
    • 文档转换 (opens new window)
  • 更多在线资源
  • Changlog
  • Aboutme
GitHub (opens new window)
博文索引
笔试面试
  • 在线学站

    • 菜鸟教程 (opens new window)
    • 入门教程 (opens new window)
    • Coursera (opens new window)
  • 在线文档

    • w3school (opens new window)
    • Bootstrap (opens new window)
    • Vue (opens new window)
    • 阿里开发者藏经阁 (opens new window)
  • 在线工具

    • tool 工具集 (opens new window)
    • bejson 工具集 (opens new window)
    • 文档转换 (opens new window)
  • 更多在线资源
  • Changlog
  • Aboutme
GitHub (opens new window)
  • 数据结构与算法

    • 基础数据结构
    • 算法基本知识
    • 时间复杂度
    • 时间复杂度拓展
    • 排序算法
    • 二分法
    • 异或运算
    • 链表结构基础
    • 栈和队列
    • 递归
      • 概述
      • 递归脑图和实际实现
      • 时间复杂度-Master公式
    • 哈希表和有序表
    • 其他
  • 设计模式

  • 编程方法论

  • 分布式设计与微服务理论

  • Leetcode

  • 程序员内功
  • 数据结构与算法
2022-02-13
目录

递归

# 递归

# 概述

递归很多网上简单的说法就是:自己调用自己。其实递归不是玄学,它是有理论支撑的—系统栈。

例子:求数组中最大数的递归方法

求数组arr[L...R]中的最大值,怎么用递归方法实现。

  • 将[L...R]范围分成左右两半。左:[L...Mid],右:[Mid + 1...R]
  • 求左部分求最大值,右部分求最大值
  • [L...R]中的最大值,是max{左部分求最大值,右部分求最大值}

第二步,是个递归过程,当范围只有一个数,就可以不用在递归了。

public class GetMax {

  public static int getMax(int[] arr) {
    return process(arr, 0, arr.length - 1);
  }

  // arr[L..R]范围上求最大值  L ... R   N
  public static int process(int[] arr, int L, int R) {
    // arr[L..R]范围上只有一个数,直接返回
    if (L == R) { 
      return arr[L];
    }
    // L...R 不只一个数,mid = (L + R) / 2
    int mid = L + ((R - L) >> 1);
    int leftMax = process(arr, L, mid);
    int rightMax = process(arr, mid + 1, R);
    return Math.max(leftMax, rightMax);
  }

}

# 递归脑图和实际实现

对于新手来说,在分析递归函数的时候,把调用的过程画出结构图(递归函数脑图,即递归调用树),这有利于分析递归。

递归底层是利用系统栈实现的。

任何递归函数都一定可以改成非递归。

# 时间复杂度-Master公式

master公式:T(N)=a⋅T(Nb)+O(Nd)T(N) = a \cdot T(\frac{N}{b}) + O(N^d)T(N)=a⋅T(bN​)+O(Nd)

N:父问题的样本量
N/b:子问题的样本量, 划分为子问题的规模
a:子问题调用的次数
O(N^d):其他的步骤复杂度
  1. logbalog_{b}alogb​a > d -> 复杂度为 O(Nlogba)O(N^{log_{b}a})O(Nlogb​a)
  2. logbalog_{b}alogb​a = d -> 复杂度为 O(Nd⋅logN)O(N^d \cdot logN)O(Nd⋅logN)
  3. logbalog_{b}alogb​a < d -> 复杂度为 O(Nd)O(N^d)O(Nd)

master公式的适用范围:父问题划分为子问题的规模是一样的。

例如,上面的例子求数组中最大数的递归方法,它的父问题的样本量为N,子问题的规模为 N/2,调用次数a为2,除了递归调用外的操作的时间复杂度为O(1)O(1)O(1),所以d=0。

所以它的Master公式为T(N)=2⋅T(N2)+O(N0)T(N) = 2\cdot T(\frac{N}{2}) + O(N^0)T(N)=2⋅T(2N​)+O(N0),符合log22log_{2}2log2​2 > 0,所以它的时间复杂度为O(Nlog22)=O(N)O(N^{log_{2}2}) = O(N)O(Nlog2​2)=O(N)。

#数据结构与算法
上次更新: 5/21/2023, 11:34:33 PM
哈希表和有序表

哈希表和有序表→

最近更新
01
2025
01-15
02
Elasticsearch面试题
07-17
03
Elasticsearch进阶
07-16
更多文章>
Theme by Vdoing
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式