【基础算法-2】递归

本文介绍了递归的基本概念,通过实例展示了如何在Java中实现阶乘、反向打印字符串、二分查找、排序算法(冒泡和插入)以及斐波那契数列的递归和备忘录法。还涉及了汉诺塔和杨辉三角的多路递归以及数组记忆法的优化技巧。
摘要由CSDN通过智能技术生成

学习目标:

掌握递归


学习内容:

  1. 递归相关例题

递归:

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

翻译翻译:
深入到最里层叫递,
从最里层出来叫归。

说明:
1.自己调用自己,即解决方案是一样的
2.每次调用,函数处理的数据会较上次缩减
3.内层函数调用完成,外层函数才能调用完成


例1:求阶乘

    public static int f(int n) {
        if (n == 1) return 1;
        return n * f(n - 1);
    }

例2:反向打印字符串

    public static void f(int n,String str){
        if(n==str.length()){
            return;
        }
        f(n+1,str);
        System.out.println(str.charAt(n));
    }

例3:递归二分查找

    //递归二分查找
    public static int f(int[] a, int target, int low, int high) {
        if (low > high) { //没找到
            return -1;
        }
        int mid = (low + high) >>> 1;
        if (target < a[mid]) {
            return f(a, target, low, mid - 1);
        } else if (target > a[mid]) {
            return f(a, target, mid + 1, high);
        } else return mid;
    }

例4: 递归冒泡排序

    public static void bubble(int[] a, int j) {
        if (j == 0) return;
        int x = 0;//每次交换时x=i,排序一遍后x的右边元素都已经排序好,下一趟以x为上界即可
        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:递归插入排序

    public static void insertion(int[] a, int low) {
        if (low == a.length) {
            return;
        }
        int t = a[low];
        int i = low - 1; //已排序区域的指针
        while (i >= 0 && a[i] > t) { //没有找到排序位置
            a[i + 1] = a[i]; //空出插入位置
            i--;
        }
        //找到插入位置
        a[i + 1] = t;
        insertion(a, low + 1);
    }

例6:斐波那契数列

原始递归版:

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

备忘录法改进:
思路是用一个数组存储已经计算过的f(n)对应的值,当再次需要计算f(n)时可以直接根据索引查询。

    //斐波那契数列-备忘录版
    public static 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;
        return cache[n];
    }

    public static int fibonacci(int n) {
        int[] cache = new int[n + 1];
        Arrays.fill(cache, -1); //初始值为-1,便于判断是否存储过
        cache[0] = 0;
        cache[1] = 1;
        return f(n,cache);
    }

多路递归:


例1:汉诺塔

public class HanoiTower {
    static LinkedList<Integer> a = new LinkedList<>();
    static LinkedList<Integer> b = new LinkedList<>();
    static LinkedList<Integer> c = new LinkedList<>();

    //初始化
    static void init(int n){
        for (int i = 0; i < n; i++) {
            a.addLast(i);
        }
    }

    static void move(int n,LinkedList<Integer> a,
                     LinkedList<Integer> b,
                     LinkedList<Integer> c){
        if(n==0)return;
        move(n-1,a,c,b);
        c.addLast(a.removeLast());
        move(n-1,b,a,c);
    }

    public static void main(String[] args) {
        init(3);

        print();
        move(3,a,b,c);
        System.out.println("-----------");
        print();
    }

    //打印汉诺塔
    private static void print() {
        System.out.println(a);
        System.out.println(b);
        System.out.println(c);
    }
}

例2:递归杨辉三角

public class PascalTriangle {
    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);
    }

    public static void print(int n) {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j <= i; j++) {
                System.out.print(element(i, j));
            }
            System.out.println();
        }
    }

    public static void main(String[] args) {
        print(4);
    }
}

也可以考虑采用数组记忆法,利用空间换取时间从而优化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值