蓝桥杯-递归与循环
2016-09-01 20:18
267 查看
珍惜作者劳动成果 转载请注明出处
致谢蓝桥杯
有时候, 为栈限制, 需要”尾递归”
Java不支持尾递归
有些语言没有循环语句, 只能使用递归
不要忘记递归的“出口”
先上递归代码
我们这样理解, 上级来了一个任务 , 我要安排下级, 但是我也要做一些事情(打印) , 但是又不能无限制的安排下去(出口) .
在n > 0的前提下进行递归, 之后打印n
那我们考虑这样一个问题: 如果我不想先递归再打印,我要先打印再递归呢 ? 是不是觉得不好构造呢? 看代码
所以说:
一旦发现递归无法表达, 说明我们的方法参数设置有问题!
出口:
if(…) f(..); 也就是在某种情况下就不进行递归了
也可以在递归之前做一个检查, 例如: if(…) return;
不能相似的原因很可能缺少参数
递归与数学上的递推公式很类似
首先我们看, 如果只有参数, 我们很难表达递归, 所以我们的参数需要修改, 这里提供三种修改思路:
1, 参数可以传入(int[] a, begin)
2, 参数可以传入(int[] a, end)
3, 折半求和, 可以出入参数(int[] a, begin, end)
为了方便大家了解, 先列出系统做法:
分析一下: 可以先比较第0个字符, 剩下的交由”下级” 去完成啊
注意每次调用的层次不同
注意每次分配形参并非同一变量
注意返回的次序
其实递归调用并不是特殊的调用, 只是主调函数和被调函数相同. 每次调用都会有现场保护(保护当前方法的状态) 并且压栈, 之后在外围方法执行完后出栈
致谢蓝桥杯
递归与循环
理论上, 任何循环都可以重写为递归形式有时候, 为栈限制, 需要”尾递归”
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)); }
递归调用
递归调用仅仅是被调函数恰为主调函数注意每次调用的层次不同
注意每次分配形参并非同一变量
注意返回的次序
其实递归调用并不是特殊的调用, 只是主调函数和被调函数相同. 每次调用都会有现场保护(保护当前方法的状态) 并且压栈, 之后在外围方法执行完后出栈
相关文章推荐
- 【蓝桥杯学习记录】【1】递归与循环(1)从循环到递归
- 【蓝桥杯学习记录】【3】递归与循环(3)递归真题
- 【蓝桥杯学习记录】【2】递归与循环(2)递归的实际应用
- 蓝桥杯常用算法知识点:1.递归与循环
- 蓝桥杯辅导视频学习-递归与循环
- [斐波那契数]循环与递归
- 经典面试题:二输入一颗二元查找树,得到树的镜像(递归和循环实现)
- 函数式编程和过程式编程--对递归和循环的思考
- 蓝桥杯 基础练习 Sine之舞 【递归简单运用】
- 蓝桥杯考试 递归题:找钱/等公交车1
- 递归和循环---从EasyUI Tree 发现自己的硬伤
- 斐波那契数组-递归和循环实现
- 专业术语之------迭代,循环,遍历,递归的区别
- 限制递归次数,避免无限循环
- 递归转化为循环
- JavaScript的递归之递归与循环示例介绍
- 算法系列之十五:循环和递归在算法中的应用
- 程序员面试宝典笔记3--循环递归概率
- 蓝桥杯:马虎的算式(非递归)
- 单链表逆序:通过递归和循环实现。