剑指offer+面试题10-递归和循环-斐波那契数列(java解答)

递归和终止

递归:在一个函数内部调用这个函数自身

循环:通过设置计算的初始值及终止条件,在一个范围内重复运算

对比:

  • 递归实现代码更简洁,更易于实现
  • 递归是函数自身调用,有时间和空间消耗(效率差,可能出现调用栈溢出)
  • 递归中很多计算是重复的(用递归思路分析,自下而上循环实现)

题目

写一个函数,输入n,求斐波那契数列的第n项

f(n)=\left\{\begin{array}{cc}0&n=0\\1&n=1\\f(n-1)+f(n-2)&n>1\end{array}\right.

三种方法的代码实现

1. 迭代:效率很低

有很多重复

	// ======== 方法1:递归 ========
	public long Fibonacci_Solution1(int n) {
		if(n<=0)
			return 0;
		if(n==1)
			return 1;
		return Fibonacci_Solution1(n-1)+Fibonacci_Solution1(n-2);
	}

2. 循环:理想解法

  • 时间复杂度:O\left (N \right )
  • 空间复杂度:O\left (N \right )​​​​
	// ======== 方法2:循环 ========
	public long Fibonacci_Solution2(int n) {
		int[] result= {0,1};
		if (n<2)
			return result[n];
		
		long fibNMinusOne =0;
		long fibNMinusTwo=1;
		long fibN=0;
		for(int i=2;i<=n;++i) {
			fibN=fibNMinusOne+fibNMinusTwo;
			
			fibNMinusOne=fibNMinusTwo;
			fibNMinusTwo=fibN;
		}
		return fibN;
	}

3. 巧妙解法

  • 时间复杂度:O(logN)
  • 空间复杂度:O(logN)

利用数学归纳法,我们不难证明:

\begin{bmatrix}f(n)&f(n-1)\\f(n-1)&f(n-1)\end{bmatrix}=\begin{bmatrix}1&1\\1&0\end{bmatrix}^{n-1}

考虑乘方性质:

a^n=\left\{\begin{array}{lc}a^i\cdot a^i&n=2i\\a^i\cdot a^i\cdot a&n=2i+1\end{array}\right.

	// ======== 方法3:基于矩阵乘法 ========
	class Matrix2By2	//矩阵的定义
	{
		long m_00;
		long m_01;
		long m_10;
		long m_11;
		public Matrix2By2(long m00,long m01,long m10,long m11)
		{
			this.m_00=m00;
			this.m_01=m01;
			this.m_10=m10;
			this.m_11=m11;			
		}
	}
	public Matrix2By2 MatrixMultiply(Matrix2By2 matrix1, Matrix2By2 matrix2)	//矩阵的乘法
	{
		Matrix2By2 res=new Matrix2By2(
				matrix1.m_00*matrix2.m_00+matrix1.m_01*matrix2.m_10,
				matrix1.m_00*matrix2.m_10+matrix1.m_01*matrix2.m_11,
				matrix1.m_10*matrix2.m_00+matrix1.m_11*matrix2.m_10,
				matrix1.m_10*matrix2.m_10+matrix1.m_11*matrix2.m_11
				);
		return res;
	}
	public Matrix2By2 MatrixPower(int n)	//矩阵的乘方
	{
		Matrix2By2 matrix;
		if (n==1)
			matrix=new Matrix2By2(1,1,1,0);
		else if(n%2==0)
		{
			matrix=MatrixPower(n/2);
			matrix=MatrixMultiply(matrix,matrix);
		}
		else
		{
			matrix=MatrixPower(n/2);
			matrix=MatrixMultiply(matrix,matrix);
			matrix=MatrixMultiply(matrix,new Matrix2By2(1,1,1,0));
		}
		return matrix;
	}
	//斐波那契数列
	public long Fibonacci_Solution3(int n)
	{
		int[] result= {0,1};
		if(n<2)
			return result[n];
		
		Matrix2By2 powerNMinus2=MatrixPower(n-1);
		return powerNMinus2.m_00;
	}
	

测试

  • 功能测试(3、5、10)
  • 边界测试(0、1、2)
  • 性能测试(40、50、100)
	// ======== 测试代码 ========
	public static void Test(int n,int expected)
	{
		T10_Fibonacci solution=new T10_Fibonacci();
		
		if(solution.Fibonacci_Solution1(n)==expected)
			System.out.println("Test for "+n+" in solution1 passed.");
		else
			System.out.println("Test for "+n+" in solution1 failed.");
		
		if(solution.Fibonacci_Solution2(n)==expected)
			System.out.println("Test for "+n+" in solution2 passed.");
		else
			System.out.println("Test for "+n+" in solution2 failed.");
		
		if(solution.Fibonacci_Solution3(n)==expected)
			System.out.println("Test for "+n+" in solution3 passed.");
		else
			System.out.println("Test for "+n+" in solution3 failed.");
			
	}
	
	public static void main(String[] args) {
		Test(0,0);
		Test(1,1);
		Test(2,1);
		Test(3,2);
		Test(4,3);
		Test(5,5);
		Test(6,8);
		Test(7,13);
		Test(8,21);
		Test(9,34);
		Test(10,55);

		Test(40,102334155);
	}
	

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值