【面试题009】斐波那契数列
斐波那契数列
f(n) = 0 ; n = 0
f(n) = 1 ; n = 1
f(n-1) + f(n-2) ; n > 1
Fib.cpp:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
#include <iostream>
using namespace std; long long Fibonacci1(unsigned int n) { if(n <= 0) { return 0; } if(n == 1) { return 1; } return Fibonacci(n - 1) + Fibonacci(n - 2); } int main(int argc, char const *argv[]) { cout << Fibonacci1(10) << endl; return 0; } |
f(10)为例子分析递归的求解过程,
这个递归调用的树,有很多结点是重复的,而且重复的结点数会随着n的增大而急剧的增加;
实际上用递归的方法计算的时间复杂度是以n的指数方式递增的。
我们只需要想办法避免重复的计算就可以了,我们可以把得到的数列的中间项保存起来,
如果下次需要计算的时候我们先查找一下,如果前面已经计算过就不用在重复计算了。
Fib.cpp:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
#include <iostream>
using namespace std; long long Fibonacci1(unsigned int n) { if(n <= 0) { return 0; } if(n == 1) { return 1; } return Fibonacci1(n - 1) + Fibonacci1(n - 2); } long long Fibonacci(unsigned int n) { int result[2] = {0, 1}; if(n < 2) { return result[n]; } long long fibNMinusOne = 0; long long fibNMinusTwo = 1; long long fibN = 0; for(unsigned int i = 2; i <= n; ++i) { fibN = fibNMinusOne + fibNMinusTwo; fibNMinusOne = fibNMinusTwo; fibNMinusTwo = fibN; } return fibN; } int main(int argc, char const *argv[]) { cout << Fibonacci1(10) << endl; cout << Fibonacci(10) << endl; return 0; } |
运行结果:
55
55
55
Makefile:
1
2 3 4 5 6 7 8 9 10 11 12 |
.PHONY:clean
CPP=g++ CFLAGS=-Wall -g BIN=test OBJS=Fib.o LIBS= $(BIN):$(OBJS) $(CPP) $(CFLAGS) $^ -o $@ $(LIBS) %.o:%.cpp $(CPP) $(CFLAGS) -c $< -o $@ clean: rm -f *.o $(BIN) |