关于递归和递归时间复杂度的估算

递归

两个小例子:

  • 举例1: 在一个数组中找到最大值
    1. 我先找左边最大值右边最大值(以下标中间为界),两者相比较,较大的就是全局最大值
    2. 我直接贴代码了哈:
      
      //结束条件
              if (L >= R) {
                  return array[L];
              }
      
              //找到中间位置,划分为左右两边
              int mid = (L + R) / 2;
      
              //左边最大值
              int maxLeft = getMax(array, 0, mid);
              //右边最大值
              int maxRight = getMax(array, mid + 1, R);
      
              //返回左右两边最大值
              return Math.max(maxLeft, maxRight);
      
      
  • 怎么理解呢?
    • 我画了个图:
      • 本例递归原理图
  • 举例2:冒泡排序的递归实现:
    • 因为冒泡排序的原理就是每一圈都让数组中的前后两个元素比较,大的放后面,小的放前面,所以我们这里采用递归就要分为两步:
      • 说明,这里的start第一圈就是下标0,end在第一圈就是数组长度
      1. 每一圈递归,其实就是遍历数组,让其两两比较,代码如下:
        if (start < end - 1) {
                   if (array[start] > array[start + 1]) {
                       swap(start, start + 1, array);
                   }
                   bubbleSort(array, start + 1, end);
               } else {
                   return;
               }
        
        
      2. 让数组不断变成一个更小的数组(因为每一圈结束最后一个都是最大的),可以理解为递归圈数,代码如下:
      bubbleSort(array, start, end - 1);
      
      1. 完整代码我放github了,要的话自己可以看看:***冒泡排序的递归版***
      2. 这个就拿来当作理解就可以了,正式用的时候还是循环,不要用递归!不要用递归!不要用递归!
  • 注意:
    1. 任何递归行为都可以变成非递归.
    2. 递归实际上就是在不停的压栈弹栈,很浪费空间.
    3. 循环基本都可以变递归,不过不建议使用递归,递归容易出问题,还不好理解,占用空间还多,除了代码简练一点.

递归时间复杂度怎么分析:

  • 看这样一个用于估计递归时间复杂度一个通式(叫做master公式):
    • T(N) = a * T(N / b) + O(N^d).
      • 这个式子是用做第一次划分的过程的时候的,后面的划分不用管.
      • 其中,T(N)表示样本量为N的情况下的时间复杂度,你就理解为T就是Time的缩写;a表示子过程的次数;N / b表示子过程的样本量;O(N^d)(这是N的d次方哈)表示除了调用子过程以后所需要的时间复杂度,下面我们以求最大值为例进行分析.
      • 由于我们把整个数组划分为了左右两个部分,两边的样本量都是(N/2),所以说左边的时间复杂度就是T(N/2),而又有左右两个部分,所以一共要两个T(N/2)的时间复杂度,即2*T(N/2).
      • 除了调用子过程意外,我们只需要对数组中元素两两比较,这个是常数级别的操作,所以最后一项O(N^d)O(1).
      • ***从这里我们可以看出,上述求最大值的时间复杂度为**T(N) = 2T(N/2) + O(1),就相当于a=2,b=2,d=0***.
    • master的公式是有适用范围的:那就是划分子过程的时候,划分的子过程的规模必须是一样的,才可以用master公式.
  • 对满足这个公式的算法有几个快捷使用公式:
    1. log(b,a) > d --> 复杂度为O(N^log(b,a)).
    2. log(b,a) == d --> 复杂度为O(N^d * logN),(logN表示以10为底).
    3. log(b,a) < d --> 复杂度为O(N^d).
    4. 注意:
      1. 这里的log(b,a)都是表示以b为底,a为指数,读作以b为底的a的对数.
      2. 以1为底的任何数的对数都是0.
      3. 1的对数永远是0.
    5. 以求最大值为例进行分析:
      1. 最大值的时间复杂度为T(N) = 2*T(N/2) + O(1),就相当于a=2,b=2,d=0,所以log(b,a) == log(2,2),其值为1,是大于d=0的,所以其具体复杂度为O(N^log(b,a)) => O(N^1) == O(N).
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值