在我的大学里,我被要求为Fibonacci系列写一个JAVA程序。 我使用递归来编写该程序。
但是,助理讲师说我的算法效率不高,并要求我分析。 他补充说,按照惯例,迭代适用于该程序而不是递归。
如何分析我们的算法?如何在迭代和递归中检查空间和时间复杂度?就在这时,我发现这些东西和程序的正确性一样重要。
答案 0 :(得分:5)
作为一个小组:
因此,只要步数限制为可管理的小数量,您就可以进行递归。因为您将确信堆栈永远不会溢出,同时递归代码为compact and elegant
。
如果您想探索更多这些可能会有所帮助。 Recursion vs loops和 Recursion or Iteration?
修改强> 正如@MrP所指出的,某些编译器可以优化一些special递归。
答案 1 :(得分:2)
它与算法的复杂性没有任何关系:当你使用递归时 - 每次调用都会在堆栈上创建一个新帧 - 所以如果递归太深,你可能会遇到StackOverflow:)
通过使用迭代 - 您在一个循环(可能)中运行在相同的空间(覆盖参数之前的值),这从StackOverflow的角度来看更快,更安全。
答案 2 :(得分:2)
我建议您按照http://nptel.iitm.ac.in/courses.php?disciplineId=106链接查找一些设计和算法分析的讲座。它是设计算法的基本概念。祝你好运。
答案 3 :(得分:1)
斐波纳契系列的最大问题是算法的时间复杂度,当你使用简单的递归时,你将重新计算所有内容并进行大量的双重工作。这是因为当你使用
计算fib(n)时int fib(int n) {
if (n < 2) { return 1; }
return fib(n-1) + fib(n-2)
}
你将计算fib(n-1),它计算fib(n-2)和fib(n-3)。但是为了计算fib(n),你已经计算了fib(n-2)。为了改善这一点,您需要存储临时结果。使用迭代通常更容易,从i = 0开始到n。这样,您可以轻松存储最后两个结果,并避免反复计算相同的值。
查看算法是否有效的一种简单方法是尝试解决一些越来越难的例子。您还可以更准确地计算它。以上面的斐波那契为例。调用fib(n)会带来复杂性O(fib(n)) = O(fib(n-1)) +O(fib(n-2)) + 1
(让我们只需要加1)。我们假设O(fib(0)) = O(fib(1)) = 1
。这意味着O(fib(2)) = 3, O(fib((3)) = 5, O(fib(4)) = 9
。正如你所看到的,这个系列比斐波那契系列本身更快!这意味着大量增加的复杂性。
当你有一个从0到n的for循环的迭代算法时,你的复杂性会按n的顺序扩展,这会更好。
有关详细信息,请查看big-o表示法。