我们先来看什么是递归
什么是递归?
从前有座山,山里有座庙,庙里有个老和尚,正在给小和尚讲故事呢
!故事是什么呢?
“从前有座山,山里有座庙,庙里有个老和尚,正在给小和尚讲故事呢!
故事是什么呢?
‘从前有座山,山里有座庙,庙里有个老和尚,正在给小和尚讲故事呢! 故事是什么呢?……’”
递归的解题思路
递归程序的基本步骤:
(1) 初始化算法。递归程序通常需要一个开始时使用的种子值(seed value)。要完成此任务, 可以向函数传递参数,或者提供一个入口函数, 这个函数是非递归的,但可以为递归计算设 置种子值。
(2) 检查要处理的当前值是否已经与基线条件相匹配。如果匹配,则进行处理并返回值。
(3) 使用更小的或更简单的子问题(或多个子问题)来重新定义答案。
(4) 对子问题运行算法。
(5) 将结果合并入答案的表达式。
(6) 返回结果。
需要注意的点:
• 递归出口(终止递归的条件)
• 递归表达式(规律)
记忆化
我们将进一步研究递归可能出现的重复计算问题。 然后我们将提出一种常用的技术, 称为记忆化(memoization),可以用来避免重复计算问题
记忆化是一种优化技术,主要用于加快计算机程序的速度,方法是存储昂贵的函数调 用的结果,并在相同的输入再次出现时返回缓存的结果
简单点:就是用存储来存中间值,避免重复计算
总结
递归是一门伟大的艺术,使得程序的正确性更容易确认,而不需要牺牲性能,但这需 要程序员以一种新的眼光来研究程序设计。对新程序员 来说,命令式程序设计通常 是一个更为自然和直观的起点,这就是为什么大部分程序设计说明都集中关注命令式 语言和方法的原因。 不过,随着程序越来越复杂,递归程序设计能够让程序员以可 维护且逻辑一致的方式更好地组织代码
什么是“栈”?
关于“栈”,有一个非常贴切的例子,就是往枪里面装子弹。装子弹的时候都是从前往 后一个一个进;打枪发射子弹的时候,是后装的子弹先出,先进的子弹后出,子弹不能 从中间任意出。后进者先出,先进者后出,这就是典型的“栈”结构。
栈相对数组和链表貌似只有限制没有任何优势。其实从功能上来说,数组或链表确实可 以替代栈,但是存在即合理,每⼀种数据结构都是在特定的使⽤场景下的抽象,⽽且, 数组或链表虽然操作上的确灵活⾃由,但使⽤时就⽐较不可控,⾃然也就更容易出错。 当某个数据集合只涉及在⼀端插⼊和删除数据,并且满⾜后进先出、先进后出的特性, 这时我们就应该⾸选“栈”这种数据结构。
栈的插入删除操作 栈的操作只允许在一端插入和删除数据,仅在表尾进行插入和删除操作,这一端被称为 栈顶,另一端称为栈低,是一种“操作受限”的线性表。
push入栈:向一个栈插入新元素称为进栈(入栈或压栈)新元素放在栈顶元素上面,使 之成为新的栈顶元素; pop出栈:从一个栈删除元素称为出栈或退栈,是将栈顶元素删除掉。
⾸先取出近添加的数据的⽅法称为“后进先出”(Last In First Out)简称:LIFO
栈的应⽤场景
表达式的转换:中缀转后缀与求值
递归⽅式就是函数⾃身调⽤⾃身,当递归每次调⽤⾃身时,可以看作是⼊栈的过程,当递 归条件满⾜后,结束时递归再⼀级⼀级的返回,返回过程可以看作是出栈的过程。递归和 栈的实现过程可以看出都是符合“先进后出,后⼊先出”的原则,所以递归⽅式其实可以转 化为栈的⽅式来实现。
对于⼆叉树的遍历,先序、中序、后序遍历都可以⽤到递归⽅法实现,既然递归可以转化 为栈,那么如何把对⼆叉树的遍历也改为⽤栈的思想来实现
栈实现综合计算器
请输⼊⼀个表达式,计算式:7*2*2-5+1-5+3-3 请问计算机底层如何运算得到结果?注意不是简单的把算式列出运算,对于计算机来说他是⼀ 个字符串。
思路:
1、通过index值遍历表达式
2、如果发现是⼀个数字⼊数栈
3、如果扫描到的是符号分以下情况:
如果符号栈为空直接⼊栈
如果符号栈有操作符进⾏⽐较
如果当前的操作符的优先级⼩于或者等于栈中的操作符。需要从数栈中pop出2个 数,再从符号栈中pop出⼀个符号进⾏运算,将得到的结果⼊数栈,然后将当前 操作符⼊符号栈
如果当前的操作符的优先级⼤于栈中的操作符直接⼊符号栈。
4、当表达式扫描结束就顺序的从数栈和符号栈中pop相应的数和符号并运⾏
5、后在数栈中只有⼀个数字就是表达式的结果
/**
* 有效括号
* @author: William
* @time:2022-03-10
*/
public class Num20 {
//map记录括号关系,栈放左括号
public boolean isValid(String s) {
Map<Character, Character> map = new HashMap<>();
map.put(')', '(');
map.put(']', '[');
map.put('}', '{');
Stack<Character> stack = new Stack<>();
for(int i = 0; i < s.length(); i++){
switch(s.charAt(i)){
case '(':
case '[':
case '{':
stack.push(s.charAt(i));
break;
case ')':
case ']':
case '}':
//栈空了或者右括号匹配不上左括号
if(stack.isEmpty() || map.get(s.charAt(i)) != stack.peek()) return false;
//配对成功,弹出左括号
stack.pop();
break;
}
}
//判断左括号有没有多
return stack.isEmpty();
}
public boolean isValid1(String s) {
int n = s.length();
if(n % 2 == 1) return false;
Map<Character, Character> pairs = new HashMap<Character, Character>(){
{
put(')', '(');
put(']', '[');
put('}', '{');
}};
Deque<Character> stack = new LinkedList<Character>();
for(int i = 0; i < n; i++) {
char ch = s.charAt(i);
if(pairs.containsKey(ch)) {
if(stack.isEmpty() || stack.peek() != pairs.get(ch)) {
return false;
}
stack.pop();
}else {
stack.push(ch);
}
}
return stack.isEmpty();
}
//用哈希提前返回
private static final Map<Character,Character> map = new HashMap<

最低0.47元/天 解锁文章
5万+

被折叠的 条评论
为什么被折叠?



