什么是递归

递归是一种思想

递归三大要素

搞清楚这个递归函数是要干什么

对于递归,最主要的搞清楚这个递归函数是要干什么,要完成什么

    //计算n的阶乘
    int f(int n) {
       
    }
寻找递归结束的条件

如果递归没有结束语句就会出现栈溢出等问题。我们需要找到当参数为什么时候递归结束,之后把参数返回。

    //计算n的阶乘
    int f(int n) {
        if (n == 1) {
            return 1;
        }
    }
找出函数的等价关系

我们要不断缩小参数范围,缩小之后我们可以通过一些辅助变量或者操作,使原函数的结果不变。如f(n)= f(n-1)*n
完善代码

int f(int n) {
        if (n <= 2) {
            return n;
        }
        return n * f(n-1);
    }

我们来看几个需要用到递归的案例来使用递归

斐波那契数列

一个斐波那契数列的大概样式是:1、1、2、3、5、8、13、21、34…即f(n) = f(n-1) + f(n-2)

找出递归函数功能

  int f(int n) {
    }

找出递归结束条件

int f(int n) {
        //递归结束条件
        if (n <= 2) {
            return 1;
        }
    }

找出函数的等价关系式

int f(int n) {
        //递归结束条件
        if (n <= 2) {
            return 1;
        }
        //等价关系式
        return f(n - 1) + f(n - 2);
    }

优化:
对于上面的递归调用,如计算f(8)
在这里插入图片描述
可以看到在递归的过程中f(5)计算了2次,其他也都计算了多次。
我们可以将每次计算出的f(n)保存在一个数组中,下次调用时候如果计算到相同的f(n)可以直接从数组中获取,提高运行效率。
代码如下:

    int f(int n) {
        //递归结束条件
        if (n <= 2) {
            return n;
        }
        //判断有没有计算过
        if (arr[n] != 0) {
            return arr[n];
        }
        //等价关系式
        arr[n] = f(n - 1) + f(n - 2)
        return arr[n];
    }
小青蛙跳台阶

小青蛙跳上一个N级台阶,它每次可以跳1级,也可以跳2级,问跳上所有台阶有多少种跳法
分析:
结束条件:当青蛙跳到最后第二格时候有两种跳法,当跳到最后一格时只有 一种跳法
等价关系:n级台阶,小青蛙第一次跳了1格,剩下n-1级有f(n-1)种跳法;
第一次跳2格,剩下n-2级台阶有f(n-2)种跳法,依次类推,知道n小于等于2。
代码如下:

       int f(int n) {
        //递归结束条件
        if (n <= 2) {
            return n;
        }
        //等价关系式
        return f(n - 1) + f(n - 2);
反转链表

这是leetcode中的一道非常经典的题目
1、第一递归函数功能

   Node reverseLiset(Node head) {
  }

2、结束条件
当当前节点或者节点的下一个是空时候结束

  Node reverseLiset(Node head) {
     if (head == null || head.next == null) {
         return head;
     }
 }

3、寻找等价关系

    Node reverseLiset(Node head) {
     if (head == null || head.next == null) {
         return head;
     }
     Node newList = reverseLiset(head.next);
     Node t1 = head.next;
     t1.next = head;//由节点1指向节点2转为节点2指向节点1
     head.next = null;
     return newList;//将调整后的链表返回
 }
不同路径

这个和小青蛙跳台阶类似。一个机器人位于一个m*n的网格上面,每次机器人只能向下或者向右移动一格,问有多少种不同的路径。
1、递归关系
机器人能向左或者向右移动后,分别有f(m-1,n)或者f(m,n-1)种路径,类似于小青蛙。以此类推。
2、结束条件
当机器人移动至m或者n为0时候,此时机器人只有一种移动方式
代码如下

    public int path(int m, int n) {
     if (m == 0 || n == 0) {
         return 1;
     }
     return path(m - 1, n) + path(m, n - 1);
 }

同样,这种方法也可以有优化,参考斐波那契数列的优化

  private int[][] arr;
  public int path(int m, int n) {
      if (m == 0 || n == 0) {
          return 1;
      }//结束语句
      //判断之前是否计算过
      if (arr[m][n] != 0) {
          return arr[m][n];
      }
      //将计算结构保存起来
      arr[m][n] = path(m - 1, n) + path(m, n - 1);
      return arr[m][n];//返回结果
  }

时间复杂度为O(m * n),空间复杂度为O(m * n)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值