我的大学实验室有问题;
编写一个简短的程序,输出通过使用字符'c','a','r','b','o'和'n'形成的所有可能的字符串。
这似乎是一个常见的面试问题并且有详细记录。
所以我使用递归方法用Java编写它并不太难,何时或为什么选择不使用递归?什么是最简单的方法呢?
我开始编写一个计数器,它会倒计数到6,然后输出会引用char并打印字符串。
谢谢,
答案 0 :(得分:15)
是的,有很多次我不会使用递归。递归不免费,它在堆栈空间中有成本,并且通常比其他一些资源更有限。在设置和拆除堆栈帧时,还有一个时间成本,无论多么小。
举例来说,大肆吹嘘的因子函数是我可能选择迭代方法的函数,其中数字很大。计算10000!用:
def factorial (n):
if n = 1 return 1
return n * factorial (n-1)
将使用10,000个堆栈帧(假设编译器没有将其优化为迭代解决方案),相当多。迭代解决方案:
def factorial (n)
r = 1
while n > 1:
r = r * n
n = n - 1
return r
只会使用一个堆栈框架而且只使用其他一些东西。
确实,递归解决方案通常是更优雅的代码,但您必须根据环境的限制来调整它。
您的carbon
示例是我实际使用递归的示例:
例如,以下Python代码可以解决这个问题:
def recur (str, pref = ""):
# Terminating condition.
if str == "":
print pref
return
# Rotate string so all letters get a chance to be first.
for i in range (len (str)):
recur (str[1:], pref + str[:1])
str = str[1:] + str[:1]
recur ("abc")
制造
abc
acb
bca
bac
cab
cba
当然,如果你的字符串长度可以是10K,我会重新考虑它,因为这会涉及更多的堆栈级别,但是,如果你保持足够低,递归是一个可行的解决方案。
答案 1 :(得分:6)
当您的数据本质上是分层/嵌套时使用递归。当数据是线性/平坦时使用迭代。
在您的情况下,您可以对组合施加自然顺序,因此您可以将数据视为线性,但如果您将其视为树,则最终会采用递归方法。
如果算法的结构反映了底层问题的结构,那么最终会得到更易于理解的更简单的代码。不要仅仅因为你的CS201教授认为它是如此使用递归!酷!
答案 2 :(得分:4)
只需使用循环即可避免使用递归。通常避免递归,因为它使代码可读性降低,难以维护和调试。如果你的资源很少,因为paxdiablo说堆栈空间可能对你有价值,所以你也应该避免使用它。
答案 3 :(得分:4)
Algorithms and Data Structures by Niklaus Wirth有一节“何时不使用递归”,但递归是程序员的有用工具。我认为理解递归对于程序员来说是“必须的”。
您对permutation问题有一个聪明的方法。它可以递归地解决(伪代码):
private void PermutationsRecursive(string prefix, string s)
{
int N = s.Length;
if (N > 0)
for (int i = 0; i < N; i++)
PermutationsRecursive(prefix + s[i], s.Substring(0, i) + s.Substring(i + 1, N - i - 1));
else
WriteLine(prefix);
}
PermutationsRecursive("", "carbon");
答案 4 :(得分:2)
当有大量的递归调用时,您的堆栈可能会爆炸,导致StackOverflowError。好的例子是计算斐波纳契数(或河内塔问题)与基本 递归你将无法计算许多这些数字。您可以使用非重复版本。基本上递归创建了漂亮的解决方案,这是一种美德。通过使用尾递归
,您仍然可以获得良好的工作递归解决方案答案 5 :(得分:2)
正如上面的人写的那样,递归并不总是最佳解决方案(函数调用可能很昂贵并且它们会消耗堆栈,除非编译器可以优化尾递归)。但是,它特别适合你的问题。
虽然理论上可以用迭代表示每个递归算法(例如,通过用数组手动模拟调用堆栈),但有时候等效的迭代解决方案不那么优雅。这是一个示例:
text = 'carbon'
n = len(text)
for permutation_i in range(factorial(n)):
free_letters = list(text)
divisor = 1
for character_i in range(n, 0, -1):
letter = free_letters.pop(permutation_i//divisor%character_i)
print(letter, end='')
divisor *= character_i
print()