【算法】【栈和队列模块】使用递归方式逆序一个栈
前言
当前所有算法都使用测试用例运行过,但是不保证100%的测试用例,如果存在问题务必联系批评指正~
在此感谢左大神的书让我对算法有了新的感悟认识!
问题介绍
原问题
使用递归函数和栈的操作实现一个能够逆序栈的工具
如:
入栈:
98765
逆序后:
56789
解决方案
1、首先知道递归方式可以将栈值全部都弹出,但是没有办法逆序push进来
2、但是一次递归可以将任何一个值一直返回到第一层,所以想到抽取最底层
3、循环抽取最底层然后再push进去,但是只有一个栈怎么办?
4、再次递归代替循环抽取底层
解决思路,具体逻辑为:
1、通过递归的方式进行抽取栈底
2、再通过递归的方式将栈底放入栈中
时间:因为每一次抽取底部需要递归一波,一共递归n次,所以 O(n^2)
空间 O(n)
代码编写
java语言版本
public class ReverseStackUtils{
/**
* 递归取栈底并放入,通用方法
*/
public static <T> void reverse(Stack<T> stack){
try {
if(stack.isEmpty()){
return;
}else{
T t = getAndRemoveLastElement(stack);
reverse(stack);
stack.push(t);
}
}catch (Exception e){
e.printStackTrace();
}
return;
}
/**
* 取栈底值
* 1、递归的截止条件一定要在调用递归方法之前
* 2、递归方法之前就是营造一个能够截止递归的操作,如stack.pop(),而截止递归操作就是为了获取栈底
* 3、递归方法之后则是处理本次递归的剩余逻辑,如 将栈顶再放回去
*/
public static <T> T getAndRemoveLastElement(Stack<T> stack){
try {
T t = stack.pop();
if(stack.isEmpty()){
return t;
}else{
T t2 = getAndRemoveLastElement(stack);
stack.push(t);
return t2;
}
}catch (Exception e){
e.printStackTrace();
}
return null;
}
/**
* 普通方法,intger类型
* @param stack
* @return
*/
public static void reverseForInt(Stack<Integer> stack){
if (stack.isEmpty()){
return;
}
Integer curlast = getLastAndRemoveForInt(stack);
reverse(stack);
stack.push(curlast);
}
public static Integer getLastAndRemoveForInt(Stack<Integer> stack){
Integer pop = stack.pop();
if (stack.isEmpty()){
return pop;
}
Integer last = getLastAndRemoveForInt(stack);
stack.push(pop);
return last;
}
/**
* 测试用例
* @param args
*/
public static void main(String[] args) {
int[] arr = {5, 4, 3, 2, 1};
Stack<Integer> testStack = new Stack<>();
Arrays.stream(arr).forEach(u -> testStack.push(u));
System.out.println(testStack.toString());
// 逆序
ReverseStackUtils.reverseForInt(testStack);
System.out.println(testStack.toString());
}
}
c语言版本
正在学习中
c++语言版本
正在学习中
思考感悟
这道题将栈和递归的思想进行了结合,栈的每一次的pop都是递归的一次状态,每一次的递归都会存储当前的pop作为当前层递归的局部变量,而每一次的递归return都是将当前层的局部变量处理完成后返回。
比如:
1、刚开始写getLastAndRemoveForInt时,只需要写Integer pop = stack.pop();即可,但是总会有空的时候,所以这个时候需要判断stack如果是空才会返回,但是我们想要返回底值,所以stack为空时就是当前底值,直接返回当前值pop
2、返回之后走到的应该是上一层调用递归处的下一句话(stack.push(pop);),而返回值就是下一层的返回值last,除了last以外,其他的状态都要“收尾”,也就是重新放回stack,因此(stack.push(pop);),最后再将底值返回给上一层继续调用处的后半段代码。
写在最后
方案和代码仅提供学习和思考使用,切勿随意滥用!如有错误和不合理的地方,务必批评指正~
如果需要git源码可咨询2260755767@qq.com或在评论区回复即可.
再次感谢左大神的书对我算法的指点迷津!
相关文章
- LeetCode 的回溯算法题目用这个模板解题,一网打尽,so easy!!!
- 【算法】【字符串模块】重新排列字符串数组使得字符串数组整体顺序最小或最大
- 【算法】【字符串模块】字符串翻转系列问题
- 【算法】【递归与动态规划模块】纸牌博弈问题(多线路型递归)
- 【算法】【二叉树模块】通过先序遍历和中序遍历获取后序遍历数组(不重构二叉树)
- 【算法】【栈和队列模块】猫狗队列:使用队列收纳两种不同的元素并且能够实时获取
- 【算法】【栈和队列模块】一个能够实时获取最小值的栈结构
- 【算法】【二叉树模块】在二叉树中找到累加和为指定值的最长路径长度
- 【算法】【矩阵与数组模块】求数组中和为给定值的最长子数组长度系列问题
- 【算法】【链表模块】一种奇怪的方式删除单链表中的值
- 【算法】【链表模块】单链表删除重复节点
- 【算法】【链表模块】两个单链表寻找交点
- 【算法】【链表模块】单链表解决约瑟夫问题
- 【算法】【栈和队列模块】求一个[0,1]矩阵中最大的1矩阵面积
- Google Earth Engine——VNP13算法过程产生三种植被指数。(1)归一化差异植被指数(NDVI),(2)增强植被指数(EVI),以及(3)增强植被指数-2(EVI2)。
- 基于SAGE算法的宽带信道参数提取算法的MATLAB仿真
- Lucas-Kanade optical flow method for 3-D源码程序——三维LK光流提取算法
- C#,图论与图算法,有向无环图(DAG,Directed Acyclic Graph)的最短路径(Shortest Path)算法与源代码
- JAVA集合--解决哈希冲突的寻址算法及代码示例
- java中驼峰与下横线格式字符串互转算法
- 华为OD机试 - 双十一(Python) | 机试题+算法思路+考点+代码解析 【2023】
- 秒懂算法 | 矩阵连乘问题
- 【基础算法】排序-复杂排序之二(找出第K大的数)
- Andrew Ng机器学习笔记+Weka相关算法实现(四)SVM和原始对偶问题
- password技术应用设计实践-安全信息传输系统(SITS)(用Java实现DES、RSA、MD5算法)
- 蓝桥杯 之 算法训练 排序
- 数字法则:机器人、大数据和算法将重塑未来