缓存解决方案中的斐波那契数列
Fibonacci in a cached solution
我在 c++ 中学习了一个记忆的斐波那契解决方案作为
#include<iostream>
using namespace std;
int F[51];
int fib(int n) {
if (n<=1)
{
return n;
}
if (F[n] != -1)
{
return F[n];
}
F[n] = fib(n-1) + fib(n-2);
return F[n];
}
int main()
{
for (int i=0; i<51; i++)
{
F[i] = -1;
}
int n;
cout<<"Give me an n: ";
cin>>n;
int result = fib(n);
cout<<result;
}
它工作正常,
$ g++ fibonacci.cpp
$ ./a.out
Give me an n: 10
55
尝试用python
重现它
In [2]: %paste
F:List = [-1] * 50
def fib2(int:n) -> int:
if n < 2:
return n
if F[n] != -1:
return F[n]
F[n] = fib2(n-1) + fib2(n-2)
return F[n]
print(fib2(10))
然而,它报告RecursionError: maximum recursion depth exceeded in comparison
---------------------------------------------------------------------------
RecursionError Traceback (most recent call last)
<ipython-input-2-5e5ce2f4b1ad> in <module>
10 return F[n]
11
---> 12 print(fib2(10))
<ipython-input-2-5e5ce2f4b1ad> in fib2(int)
7 if F[n] != -1:
8 return F[n]
----> 9 F[n] = fib2(n-1) + fib2(n-2)
10 return F[n]
11
... last 1 frames repeated, from the frame below ...
<ipython-input-2-5e5ce2f4b1ad> in fib2(int)
7 if F[n] != -1:
8 return F[n]
----> 9 F[n] = fib2(n-1) + fib2(n-2)
10
仔细检查 python 解决方案与前面的解决方案具有相同的逻辑。
我的代码有什么问题。
试试这个:
fib_aux = [-1] * 50
def fib(n):
if n < 2:
return n
else:
if fib_aux[n] < 0:
fib_aux[n] = fib(n - 1) + fib(n - 2)
return fib_aux[n]
有了列表,你也可以这样做来避免递归:
fib_aux = [0, 1]
def fib(n):
m = len(fib_aux)
for i in range(m, n + 1):
fib_aux.append(fib_aux[i - 1] + fib_aux[i - 2])
return fib_aux[n]
除了管理列表,您还可以使用通用的记忆功能:
def memoize(f):
h = {}
def g(*arg):
if arg not in h:
h[arg] = f(*arg)
return h[arg]
return g
@memoize
def fib(n):
return n if n < 2 else fib(n - 1) + fib(n - 2)
有关 Python 装饰器 (@) 的更多信息,请参阅 this question。
请注意,由于递归限制,第一个和最后一个方法可能会失败。第二种解决方案不使用递归。但是,如果您只需要几个 fib(n)
的值来获得较大的 n
,则有使用参数加倍的更快解决方案(请参阅 Math.SE 上的 this)。
类型提示不正确,这对我有用:
# fixed type hint
F:list = [-1] * 50
# fixed type hint
def fib2(n:int) -> int:
if n < 2:
return n
if F[n] != -1:
return F[n]
F[n] = fib2(n-1) + fib2(n-2)
return F[n]
fib2(49)
=> 7778742049
问题出在你的类型提示上:应该是n: int
而不是int: n
。
在普通脚本中,您会得到一个 NameError
,如下所示:
def fib2(int: n):
pass
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-19-2a2734193e18> in <module>()
----> 1 def fib2(int: n):
2 pass
NameError: name 'n' is not defined
您的情况是您可能在 运行 之前在 IPython 中定义的其中一个单元格中定义了 n
。所以,你没有得到 'NameError',但你的参数得到了名称 int
,函数中使用的 n
是你之前在某处使用的全局 n
。如果是大于2的数,你的递归调用将永远不会结束:
n = 3 # might have been in some other cell
F = [-1] * 101
def fib2(int: n):
if n < 2:
return n
if F[n] != -1:
return F[n]
F[n] = fib2(n-1) + fib2(n-2)
return F[n]
print(fib2(100))
---------------------------------------------------------------------------
[...]
RuntimeError: maximum recursion depth exceeded in comparison
只需按正确的顺序编写类型提示,一切都很好:
F = [-1] * 101
def fib2(n: int):
if n < 2:
return n
if F[n] != -1:
return F[n]
F[n] = fib2(n-1) + fib2(n-2)
return F[n]
print(fib2(100))
# 354224848179261915075
我在 c++ 中学习了一个记忆的斐波那契解决方案作为
#include<iostream>
using namespace std;
int F[51];
int fib(int n) {
if (n<=1)
{
return n;
}
if (F[n] != -1)
{
return F[n];
}
F[n] = fib(n-1) + fib(n-2);
return F[n];
}
int main()
{
for (int i=0; i<51; i++)
{
F[i] = -1;
}
int n;
cout<<"Give me an n: ";
cin>>n;
int result = fib(n);
cout<<result;
}
它工作正常,
$ g++ fibonacci.cpp
$ ./a.out
Give me an n: 10
55
尝试用python
重现它In [2]: %paste
F:List = [-1] * 50
def fib2(int:n) -> int:
if n < 2:
return n
if F[n] != -1:
return F[n]
F[n] = fib2(n-1) + fib2(n-2)
return F[n]
print(fib2(10))
然而,它报告RecursionError: maximum recursion depth exceeded in comparison
---------------------------------------------------------------------------
RecursionError Traceback (most recent call last)
<ipython-input-2-5e5ce2f4b1ad> in <module>
10 return F[n]
11
---> 12 print(fib2(10))
<ipython-input-2-5e5ce2f4b1ad> in fib2(int)
7 if F[n] != -1:
8 return F[n]
----> 9 F[n] = fib2(n-1) + fib2(n-2)
10 return F[n]
11
... last 1 frames repeated, from the frame below ...
<ipython-input-2-5e5ce2f4b1ad> in fib2(int)
7 if F[n] != -1:
8 return F[n]
----> 9 F[n] = fib2(n-1) + fib2(n-2)
10
仔细检查 python 解决方案与前面的解决方案具有相同的逻辑。
我的代码有什么问题。
试试这个:
fib_aux = [-1] * 50
def fib(n):
if n < 2:
return n
else:
if fib_aux[n] < 0:
fib_aux[n] = fib(n - 1) + fib(n - 2)
return fib_aux[n]
有了列表,你也可以这样做来避免递归:
fib_aux = [0, 1]
def fib(n):
m = len(fib_aux)
for i in range(m, n + 1):
fib_aux.append(fib_aux[i - 1] + fib_aux[i - 2])
return fib_aux[n]
除了管理列表,您还可以使用通用的记忆功能:
def memoize(f):
h = {}
def g(*arg):
if arg not in h:
h[arg] = f(*arg)
return h[arg]
return g
@memoize
def fib(n):
return n if n < 2 else fib(n - 1) + fib(n - 2)
有关 Python 装饰器 (@) 的更多信息,请参阅 this question。
请注意,由于递归限制,第一个和最后一个方法可能会失败。第二种解决方案不使用递归。但是,如果您只需要几个 fib(n)
的值来获得较大的 n
,则有使用参数加倍的更快解决方案(请参阅 Math.SE 上的 this)。
类型提示不正确,这对我有用:
# fixed type hint
F:list = [-1] * 50
# fixed type hint
def fib2(n:int) -> int:
if n < 2:
return n
if F[n] != -1:
return F[n]
F[n] = fib2(n-1) + fib2(n-2)
return F[n]
fib2(49)
=> 7778742049
问题出在你的类型提示上:应该是n: int
而不是int: n
。
在普通脚本中,您会得到一个 NameError
,如下所示:
def fib2(int: n):
pass
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-19-2a2734193e18> in <module>()
----> 1 def fib2(int: n):
2 pass
NameError: name 'n' is not defined
您的情况是您可能在 运行 之前在 IPython 中定义的其中一个单元格中定义了 n
。所以,你没有得到 'NameError',但你的参数得到了名称 int
,函数中使用的 n
是你之前在某处使用的全局 n
。如果是大于2的数,你的递归调用将永远不会结束:
n = 3 # might have been in some other cell
F = [-1] * 101
def fib2(int: n):
if n < 2:
return n
if F[n] != -1:
return F[n]
F[n] = fib2(n-1) + fib2(n-2)
return F[n]
print(fib2(100))
---------------------------------------------------------------------------
[...]
RuntimeError: maximum recursion depth exceeded in comparison
只需按正确的顺序编写类型提示,一切都很好:
F = [-1] * 101
def fib2(n: int):
if n < 2:
return n
if F[n] != -1:
return F[n]
F[n] = fib2(n-1) + fib2(n-2)
return F[n]
print(fib2(100))
# 354224848179261915075