【蓝桥杯备赛】2.递归和常见算法

【蓝桥杯备赛】2.递归和常见算法

学了这里,我们会学到1.对递归,建立起感觉2.学会评估算法性能3.能够大致预估程序的执行时间

递归

递归设计经验
  • 找到重复(子问题)
  • 找到重复问题中的变化量->参数
  • 找到参数的变化趋势->设计出口

感受:递归其实有点委托思维:我先做一部分,让递归帮我解决其他部分,然后我进行组合结果。
递归可能分解成:直接量+小规模子问题
也可以分解成多个子问题
递归解答树的顺序是 :先纵深再横
递归的本质其实就是找到递归公式

联系策略
  • 循环改递归
  • 经典递归
  • 大量练习,总结规律,掌握套路
  • 找到感觉,挑战高难度

递归训练

求阶乘
/**
     * f1(n):求n的阶乘-->f1(n-1)求n-1的阶乘
     * 找重复: n*(n-1)的阶乘,求n-1的阶乘是原问题的重复(规模更小)一子问题
     * 找变化:变化的量应该作为参数
     * 找边界:出口
     */
 static int f(int num ){
	if(num==1){
		return 1;
	}
	return f(num -1)*num;
}

打印i-j
	/**
     * 打印i到j的数字
     * 要注意是后生成的递归进程先打印
     */
    static void print(int i,int j){
        if(j<i){
            return;
        }
        System.out.print(j);
        print(i,j-1);
    }

数组求和
/**
     * 数组求和
     * 了解加参数的意识,变化的量要作为参数
     */
    static void sum(int[] arr , int i, int sum){
        if(i==arr.length){
            System.out.println(sum);
            return;
        }
        sum(arr,i+1,sum+arr[i]);
    }

翻转字符串
	/**
     * 翻转字符串
     * 思路:翻转abcd,等于翻转bcd+翻转a
     * 最后一种切蛋糕思维的题目
     */
    static String reverse(String arr){
        if(arr.length()==1){
            return arr;
        }
        //把最后一个拼接到前面
        return reverse(arr.substring(1))+arr.charAt(0);
    }


//多一个参数,不用substring的做法
static String reverse(String arr, int i){
        if(i==arr.length()-1){
            return arr.charAt(i)+"";
        }
        return reverse(arr,i+1)+arr.charAt(i);
    }

斐波那契数列
	/**
     * 斐波那契数列
     */
    static int fib(int n){
        if(n==1||n==2){
            return 1;
        }
        return fib(n-1)+fib(n-2);
    }
最大公约数
/**
     * 最大公约数
     *
     * 辗转相除法
     */
    static int gcd(int m,int n) {
        if (n == 0) {
            return m;
        }
        return gcd(n, m % n);
    }
用递归改写插入排序
	/**
     * 递归关键是找到一种良好的划分方法
     * 2.找到地推公式和等价转换
     * 对敌
     * 对数组的0-倒数第二个元素,这部分排序
     * 然后把最后一个元素插入到这个有序的部分中
     */
    static void inserSort(int[] arr,int k) {
        if (k==0){
            return;
        }
        //对前k-1个元素排序
        inserSort(arr,k-1);
        //把位置k的元素插入到前面部分
        int x = arr[k];
        int index = k-1;
        while (x<arr[index]){
            arr[index+1] = arr[index];
            index--;
        }
        arr[index+1] = x;
    }
汉诺塔问题

这个的嘀咕公式有点奇怪:它是文字哦:当只有一个盘子时,直接打印移动路径;
当盘子数量大于 1 时,先将上面 n-1 个盘子从 A 经过 C 移动到 B,然后打印移动第 n 个盘子的路径,最后将 n-1 个盘子从 B 经过 A 移动到 C

  • 汉诺塔问题
    有n个盘子,三个柱子,要把n个盘子按照原石的顺序整体移动到另一个柱子上。而且大盘子不能放在小盘子上,每次只能移动一个盘子。
    N从A移动到B, C作为辅助
    等价于:
    1、N-1移动到C, B为辅助
    2、把N从A移动到B
    3、N从C移动到B, A为辅助
    
  • 思考汉诺塔问题可以先思考两个盘子如何从A移动到C
    1.把第一个盘子先移动到辅助空间B
    2.把第二个盘子移动到to C
    3.把第一个盘子移动到C
static void printHanoiTower(int N, String from ,String to ,String help){
	if(N==1){
		 System.out.println("move "+ N + " from " + from + " to " + to);
		 return;
	}
	//先把压着它的移动到辅助空间
	printHanoiTower(N-1,from,help,to);
	System.out.println("move "+ N + " from " + from + " to " + to);
	//后置操作:让N-1从辅助空间回到原来的源空间
	printHanoiTower(N-1,help,to,from);
}

####### 二分查找

/**
     * 二分查找
     * 等价于三个子问题
     * 1、左边找
     * 2、右边找
     * 3、中间比
     */
    static void binarySearch(int[] arr,int low,int high,int target){
        if(low>high){
            return;
        }
        int mid = (low+high)/2;
        if(arr[mid]==target){
            System.out.println(mid);
            return;
        }else if(arr[mid]>target){
            binarySearch(arr,low,mid-1,target);
        }else{
            binarySearch(arr,mid+1,high,target);
        }
    }

常见的算法

希尔排序
  • 比较考验空间思维能力
/**
     * interval步径
     * @param arr
     */
    static void shellSort2(int[] arr){
        //不断地缩小增量
        for (int interval = arr.length/2; interval >0 ; interval=interval/2) {
            //这里其实是插入排序,把interval换成1就行
//            for (int i = 1; i < arr.length; i++) {
//                int target = arr[i];
//                int j =i-1;
//                while(j>-1&&target<arr[j]){
//                    arr[j+1]= arr[j];
//                    j--;
//                }
//                arr[j+1]=target;
//            }
            //这里是interval步径的插入排序
            for (int i = interval; i < arr.length; i++) {
                int target = arr[i];
                int j =i-interval;
                while(j>-1&&target<arr[j]){
                    arr[j+interval]= arr[j];
                    j-=interval;
                }
                arr[j+interval]=target;
            }
        }
    }

常见算法和递归剩下很多的例子由于我还没搞得很清楚,就先留着等日后更新。

  • 15
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值