蓝桥杯-递归与循环

珍惜作者劳动成果 转载请注明出处

致谢蓝桥杯

递归与循环

  • 理论上, 任何循环都可以重写为递归形式
    • 有时候, 为栈限制, 需要”尾递归”
    • Java不支持尾递归
  • 有些语言没有循环语句, 只能使用递归

循环改递归

  • 改为递归的关键是发现逻辑的”相似性”
  • 不要忘记递归的“出口”

循环打印案例

我们来个案例, 非常简单打印 从0到9 , 我们用循环很容易解决(当然递归也不难)

for (int i = 0; i < 9; i++) {
    System.out.println(i);
}

先上递归代码

 public static void f(int n) {
     if(n > 0) f(n-1);
     System.out.println(n);
 }

我们这样理解, 上级来了一个任务 , 我要安排下级, 但是我也要做一些事情(打印) , 但是又不能无限制的安排下去(出口) .
在n > 0的前提下进行递归, 之后打印n

那我们考虑这样一个问题: 如果我不想先递归再打印,我要先打印再递归呢 ? 是不是觉得不好构造呢? 看代码

public static void f2(int begin, int end) {
    if(begin > end){
        return;
    }
    System.out.println(begin);
    f2(begin+1, end);
}

所以说:
一旦发现递归无法表达, 说明我们的方法参数设置有问题!
出口:
if(…) f(..); 也就是在某种情况下就不进行递归了
也可以在递归之前做一个检查, 例如: if(…) return;

构造相似性

  • 如果没有明显的相似性, 需要主动的构造
  • 不能相似的原因很可能缺少参数
  • 递归与数学上的递推公式很类似

计算数组总和案例

先上循环的做法

//累加和  循环做法
public static int addAll(int[] a) {
    int x = 0;
    for (int i = 0; i < a.length; i++) {
        x += a[i];
    }
    return x;
}

首先我们看, 如果只有参数, 我们很难表达递归, 所以我们的参数需要修改, 这里提供三种修改思路:

1, 参数可以传入(int[] a, begin)

我们可以先算第0项, 加上 begin+1 到 end的和. a[begin] + (begin+1 .... 结束)
public static int f1(int a[], int begin) {
   if (begin == a.length) {
       return 0;
   }
   int x = 0;
   x = f1(a, begin + 1);
   return a[begin] + x;
}

2, 参数可以传入(int[] a, end)

同1中所说思路相同: 
(0 ... end-1) + a[end]
public static int f2(int[] a, int end) {
    if (end < 0) {
        return 0;
    }
    int x = 0;
    x = f2(a, end-1);
    return x + a[end];
}

3, 折半求和, 可以出入参数(int[] a, begin, end)

先求得mid=(begin+end)/2
在前后求和 [begin, mid) + [mid, end) 这里注意end是包括的(传参数时: f(a, a.length-1)
这里的end是不包含的!! 
主要是在判断出口的地方, 两种情况: 1, 总数为奇数 2, 总数为偶数
第3种方法可能会有更好的办法, 如果大家有更好的办法希望在评论中贴出大家一起讨论

public static int f3(int a[], int begin, int end) {
    if (begin == end-1) {
        return a[begin];
    }
    if (end - begin == 2) {
        return a[begin] + a[end - 1];
    }
    //求mid, 找到中间位置
    int mid = (begin + end) / 2;
    int x = f3(a, begin, mid);
    int y = f3(a, mid, end);
    return x + y;
}

判断字符串相等

问题: 比较两个串的内容是否相等

为了方便大家了解, 先列出系统做法:

public static boolean isSameString(String s1, String s2) {
    return s1.equals(s2);
}

分析一下: 可以先比较第0个字符, 剩下的交由”下级” 去完成啊


public static boolean f(String s1, String s2) {
    //判断两者长度, 若不等长肯定不等
    if (s1.length() != s2.length()) {
        return false;
    }
    //递归出口
    if (s1.length() == 0) {
        return true;
    }
    if (s1.charAt(0) != s2.charAt(0)) {
        return false;
    }
    return f(s1.substring(1), s2.substring(1));
}

递归调用

  • 递归调用仅仅是被调函数恰为主调函数
  • 注意每次调用的层次不同
  • 注意每次分配形参并非同一变量
  • 注意返回的次序

这里写图片描述

其实递归调用并不是特殊的调用, 只是主调函数和被调函数相同. 每次调用都会有现场保护(保护当前方法的状态) 并且压栈, 之后在外围方法执行完后出栈

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值