【发布时间】:2014-04-22 00:46:39
【问题描述】:
这个问题的依据:
我将在今年夏天毕业并获得计算机科学学位,而且我从未有过教授强调堆栈的重要性。然而,我有多个项目都专注于递归的使用。我发现递归有用且令人兴奋,并且在我的个人项目中经常使用它。
我最近参加了一次工作面试,面试官对他们问题的递归解决方案非常失望。他们想要 Stack 解决方案。我做了很多研究,但我仍然不确定何时使用哪个。
给出以下演示:
public class TestCode {
static long startTime = 0;
static long stopTime = 0;
static long totalTime = 0;
public static void main(String[] args) throws IOException {
int x = 10000;
startTime = System.currentTimeMillis();
recursiveMethod(x);
System.out.println();
stopTime = System.currentTimeMillis();
totalTime = stopTime - startTime;
System.out.println(totalTime);
System.out.println();
startTime = System.currentTimeMillis();
stackMethod(x);
System.out.println();
stopTime = System.currentTimeMillis();
totalTime = stopTime - startTime;
System.out.println(totalTime);
}
public static void recursiveMethod(int a){
if(a >= 0){
recursiveMethod(a - 1);
System.out.println("Recursion: " + a + " ");
}
}
public static void stackMethod(int a){
Stack<Integer> myStack = new Stack<Integer>();
while(a >= 0){
myStack.push(a);
a--;
}
while(myStack.isEmpty() == false){
a = myStack.pop();
System.out.println("Stack: " + a + " ");
}
}
}
两种解决方案都在大约 200 毫秒内完成。通过添加零来更改 x 的值:x = 100000 给我一个 StackOverflowError(在递归方法上)。
当我用 x 的 SAME 值注释掉递归解决方案时,程序成功运行,这意味着 Stack 解决方案的工作远远超出了递归解决方案的限制。
问题
- 为什么递归解决方案会产生与 Stack 解决方案相同的迭代次数的 StackOverflowError,但 Stack 解决方案不会出错?
- 如果 Stack 解决方案功能更强大且使用更少的内存,您何时会使用递归解决方案?
- 在选择其中一个之前必须考虑的递归和堆栈/迭代解决方案之间的根本区别是什么?
【问题讨论】:
-
递归通常为算法提供清晰的“数学”描述。然而,务实地讲,在 Java 中使用递归可能会导致未知(和大量)内存使用,当您直接控制信息时(例如在“堆栈”解决方案中),这可能会更有效。
-
Java 没有尾调用优化,因此递归会占用有限的堆栈空间。栈解决方案使用堆空间。
-
(与@Kevin 声明相关的讨论:mail.openjdk.java.net/pipermail/mlvm-dev/2010-October/…)
-
我希望您能详细说明面向堆栈的解决方案的性质,或者提出了什么问题?这些堆栈解决方案在本质上是否等同于/模拟递归解决方案的函数调用堆栈上发生的事情,还是它们有什么不同?
-
@mvw 提出的问题与树结构有关,从字符串生成树。给定 a(bcd(efg)) 创建一棵树而不使用递归。我个人遇到这个问题是因为解决了CodeEval 上的机器人运动挑战。我在那里使用了递归,但我决定尝试使用多个堆栈找到一个非递归解决方案,看看哪个更有效。
标签: java performance recursion stack