递归~~~

一.定义

计算机科学中,递归是一种解决计算问题的方法,其中解决方案取决于同一类问题的更小子集。

比如单链表递归遍历的例子:

     void f(Node node){
         if (node == null){
             return;
         }
         f(node.next);
     }

说明:

1.自己调用自己,如果说每个函数对应着一种解决方案,自己调用自己意味着解决方案是一样的(有规律的)

2.每次调用,函数处理的数据会比较上次缩减(子集),而且最后会缩减至无需继续递归

3.内层函数调用(子集处理)完成,外层函数才能算调用完成

二:思路

1.确定能否使用递归求解

2.推导出递推关系,即父问题与子问题的关系,以及递归的结束条件

:深入到最里层叫做,从最里层出来叫做,在的过程中,外层函数内的局部变量(以及方法参数)并未消失,归的时候还可以用到。

三:例题

1.求阶乘

    private static int f(int n){
        if (n == 1){
            return 1;
        }
        return n*f(n-1);
    }
2.反向打印字符

    private static void f(int n,String str){
        if (n == str.length()){
            return;
        }
        f(n+1,str);
        System.out.println(str.charAt(n));
    }
3.二分查找
   public int f(int[]a,int target,int i,int j){
       if (i>j){
           return -1;
       }
       
       int m = (i+j)>>>1;
       if (target < a[m]){
           return f(a,target,i,m-1);
       } else if (a[m] < target) {
           return f(a,target,m+1,j);
       }else {
           return m;
       }
   }
4.冒泡排序
 //j代表未排序区域右边界
 private void bubble(int[] a,int j){
       if (j == 0){
           return;
       }
       for (int i = 0;i < j;i++){
           if (a[i] > a[i+1]){
               int t = a[i];
               a[i] = a[i+1];
               a[i+1] = t;
           }
       }
       bubble(a,j-1);
   }

优化版:当某一次递归后所有值已经有序,就不需要再进行接下来的代码了

 //j代表未排序区域右边界
 //x是i在交换前i对应的位置,若未发生交换,则x不变,则x右边值都是有序的
 private void bubble(int[] a,int j){
       if (j == 0){
           return;
       }
       int x = 0;
       for (int i = 0;i < j;i++){
           if (a[i] > a[i+1]){
               int t = a[i];
               a[i] = a[i+1];
               a[i+1] = t;
               x = i;
           }
       }
       bubble(a,x);
   }
5.插入排序

   //low为未排序区域的左边界
   private void insertion(int[] a,int low){
        if (low == a.length){
            return;
        }
       int t = a[low];//low位置的值
       int i = low-1; //已排序区域指针

       while(i >= 0 && a[i] > t){  //寻找小于t的第一个位置,没有找到插入位置
           a[i+1]=a[i];   //空出插入位置,即将a[i]值赋予low,直到找到插入位置
           i--;
       }
       //找到插入位置
       if (i+1 != low){   //例如2 3 4 要插入4时,已经是有序的,不需要再赋值了
           a[i+1]=t;
       }
       insertion(a,low+1);
   }
6.斐波那契数列
(1)代码实现

   public int f(int n){
       if (n == 0){
           return 0;
       }
       if (n == 1){
           return 1;
       }
       int x = f(n-1);
       int y = f(n-2);
       return x+y;
   }

(2)变体一:兔子问题

(3)变体二:青蛙爬楼梯

(4)优化版:记忆法
   public int fibonaci(int n){
      int[] cache = new int[n+1];//若n=5,则f(5)需存入cache[5],从0开始需要6个长度
       Arrays.fill(cache,-1);//[-1,-1,-1,-1,-1,-1]
       cache[0] = 0;
       cache[1] = 1;//[0,1,-1,-1,-1,-1]
       return f(n,cache);
   }
    public int f(int n,int[] cache){
        if (cache[n] != -1){  //先在数组里找值
            return cache[n];  //找到直接返回
        }
        int x = f(n-1,cache);
        int y = f(n-2,cache);
        cache[n] = x + y;//[0,1,?,-1,-1,-1]存入数组
        return cache[n];
    }

7.杨辉三角
    //算出数字
    private static int element(int i,int j){
       if (j == 0 || i == j){
           return 1;
       }
       return element(i-1,j-1)+element(i-1,j);
    }
    //打印空格
    private static void printSpace(int n,int i){
       int num = (n-1-i)*2;
       for (int j=0;j<num;j++){
           System.out.print(" ");
       }
    }
    //打印数字
    public static void print(int n){
       for (int i=0;i<n;i++){
           printSpace(n,i);
           for (int j=0;j<=i;j++){
               System.out.printf("%4d",element(i,j));
           }
           System.out.println();
       }
    }

8.杨辉三角优化:记忆法

提前把值存入数组,就不需要重复计算

    //算出数字
    private static int element(int[][] triangle,int i,int j){
       if (triangle[i][j]>0){//先看数组里是否存在,开始时每个数都是0,若是有值则大于0
           return triangle[i][j];
       }
       if (j == 0 || i == j){
           triangle[i][j]=1;
           return 1;
       }
       triangle[i][j] = element(triangle,i-1,j-1)+element(triangle,i-1,j);
       return triangle[i][j];//将值存入数组
    }
    //打印空格
    private static void printSpace(int n,int i){
       int num = (n-1-i)*2;
       for (int j=0;j<num;j++){
           System.out.print(" ");
       }
    }
    //打印数字
    public static void print(int n){
       int[][] triangle = new int[n][];//每行有多少列不确定
       for (int i=0;i<n;i++){ //行
           triangle[i] = new int[i+1];//确定列,根据规律可得j=i+1,从第0行开始算
           printSpace(n,i);
           for (int j=0;j<=i;j++){
               System.out.printf("%4d",element(triangle,i,j));
           }
           System.out.println();
       }
    }

四:递归时间复杂度计算

1.公式法

2.展开求解

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值