剑指Offer-10:斐波那契数列
2017-12-22 11:29
381 查看
题目:
大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项。问题解析:
斐波那契数列的定义:除了第一和第二个数外,其他的元素为其前两个数的和。f(n)=⎧⎩⎨⎪⎪0n=01n=1f(n−1)+f(n−2)n>0
链接:
剑指Offer(第2版):P74思路标签:
算法:递归、循环解答:
1. C++
基于递归的斐波那契数列在每次计算的时候都存在重复的计算,其时间复杂度会随着n的增加以指数的方式递增。并且,使用递归可能会引起调用栈溢出的问题。当追求代码的简洁性,且递归的次数没有足够大时,使用递归;
当追求代码的时间效率,那么使用循环会更好。
常用的使用递归来计算斐波那契数列的解法在时间效率上并不高,所以这里使用循环来实现。
同时还有基于矩阵乘法的实现,时间复杂度O(logn),具体解释见书P76。
循环实现
long long fibnacci(unsigned n){ int result[2] = {0, 1}; if(n < 2) return result ; long long fibOne = 0; long long fibTwo = 1; long long fibCurrent = 0; for(unsigned int i=2; i<=n; ++i){ fibCurrent = fibTwo + fibOne; fibOne = fibTwo; fibTwo = fibCurrent; } return fibCurrent; } }
递归实现
long long Fibonacci_Solution2(unsigned int n) { if(n <= 0) return 0; if(n == 1) return 1; return Fibonacci_Solution1(n - 1) + Fibonacci_Solution1(n - 2); }
基于矩阵乘法的实现
#include <cassert> struct Matrix2By2 { long long m_00; long long m_01; long long m_10; long long m_11; Matrix2By2(long long m00 = 0, long long m01 = 0, long long m10 = 0, long long m11 = 0) :m_00(m00), m_01(m01), m_10(m10), m_11(m11) { } }; Matrix2By2 MatrixMultiply(const Matrix2By2& matrix1, const Matrix2By2& matrix2){ return Matrix2By2( matrix1.m_00 * matrix2.m_00 + matrix1.m_01 * matrix2.m_10, matrix1.m_00 * matrix2.m_01 + matrix1.m_01 * matrix2.m_11, matrix1.m_10 * matrix2.m_00 + matrix1.m_11 * matrix2.m_10, matrix1.m_10 * matrix2.m_01 + matrix1.m_11 * matrix2.m_11); } Matrix2By2 MatrixPower(unsigned int n) { assert(n > 0); Matrix2By2 matrix; if(n == 1) { matrix = Matrix2By2(1, 1, 1, 0); } else if(n % 2 == 0) { matrix = MatrixPower(n / 2); matrix = MatrixMultiply(matrix, matrix); } else if(n % 2 == 1) { matrix = MatrixPower((n - 1) / 2); matrix = MatrixMultiply(matrix, matrix); matrix = MatrixMultiply(matrix, Matrix2By2(1, 1, 1, 0)); } return matrix; } long long Fibonacci_Solution3(unsigned int n) { int result[2] = {0, 1}; if(n < 2) return result ; Matrix2By2 PowerNMinus2 = MatrixPower(n - 1); return PowerNMinus2.m_00; }
其他相关问题
题目1: 青蛙跳台阶问题。一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个n级台阶总共有多少种跳法。
分析:
我们将n级台阶的跳法看作是n的函数,记为f(n)。
当n=1时,只有1种跳法;
当n=2时,有跳1次2阶和跳2次1阶的2种跳法;
当n>2时,第一次跳有两种选择:一种是第一次跳1阶,此时跳法为后面剩下的n-1阶,即为f(n-1);一种是第一次跳2阶,此时跳法为后面剩下的n-2阶,即为f(n-2)。
因此,由上面的分析可以看出n阶的不同跳法的总数为f(n)=f(n-1)+f(n-2)。实际上就是斐波那契数列。
扩展:青蛙跳台改为青蛙可以一次跳1级台阶,也可以2阶,…,也可以n阶。总共的跳法,最后用数学归纳法,可以证明:f(n)=2^(n-1)。
题目2: 矩形覆盖问题
我们可以用2x1的小矩形横着或者竖着去覆盖更大的矩形。问用8个2x1的小矩阵无重叠地覆盖一个2x8的大矩阵,共有多少种方法?
分析:
我们将2x8的覆盖方法记为f(8)。用第一个小矩形覆盖大矩形最左边的时候,有两种选择:竖着放置或者横着放置。
竖着放置的时候,右边还剩下2x7的区域,记为f(7);
横着放置的时候,左上角放置一个,则对应的左下角必须还有一个小矩阵,则右边还剩下2x6的区域,记为f(6);
因此,f(8)=f(7)+f(6),可以看出,这仍然是斐波那契数列。
相关文章推荐
- 【剑指offer】面试题 10:斐波那契数列及其推广
- 剑指offer:斐波那契数列
- [九度OnlineJudge][剑指Offer]题目1387:斐波那契数列
- 【剑指Offer面试题】 九度OJ1387:斐波那契数列
- 剑指offer编程题Java实现——面试题9斐波那契数列
- 剑指offer-9-Python实现斐波那契(Fibonacci)数列
- 【剑指Offer】面试招聘题目4:斐波那契数列
- [剑指Offer] 10.矩形覆盖
- 剑指offer第9题:斐波纳西数列
- 剑指Offer10:二进制中1的个数
- 剑指offer--简易动态规划(3、10、20、26,61)
- [剑指Offer]11.斐波那契数列
- 剑指offer——面试题10:二进制中1的个数
- 剑指offer面试题10-二进制中1的个数
- 剑指offer-10.矩形覆盖
- 剑指Offer面试题10(Java版):二进制中的1的个数
- 【剑指offer】斐波那契序列与跳台阶
- 【剑指offer】7.斐波那契数列
- 剑指offer-和为s的数列
- 剑指offer10:二进制中1的个数