剑指offer刷题-变态跳台阶

【Java】 剑指offer(9) 斐波那契数列及青蛙跳台阶问题

题目描述

一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

思路分析

数学归纳法寻找规律
经过计算,发现:

当n=1时,结果为1;
当n=2时,结果为2;
当n=3时,结果为4;
当n=4时,结果为8;

因此可以推出,f(n)=2^(n-1)
每一个台阶都有跳与不跳两种情况(除最后一个台阶外),所以有2^(n-1)两种情况

代码实现:

public class Solution {
    public int JumpFloorII(int target) {
        int res =1;
        if(target <= 2)
            return target;
        for(int i = 1; i<target; i++) {
            res *= 2;
            
        }
        return res;
    }
}

PS:Java实现幂运算,通过Math.pow()函数,没有^运算。Math.pow()函数的输入分别为底数和指数。输入和输出均为double型,所以需要强制转换。return (int)Math.pow(2,target-1);

拓展:

题目描述

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

在这里插入图片描述
思路1

时间复杂度:O(n)的解法

如果直接写递归函数,由于会出现很多重复计算,效率非常底,不采用。
  要避免重复计算,采用从下往上计算,可以把计算过了的保存起来,下次要计算时就不必重复计算:先由f(0)和f(1)计算f(2),再由f(1)和f(2)计算f(3)……以此类推,计算第n个时,只需要保存第n-1和第n-2项就可以。

代码实现:

public class Fibonacci {    
	public long Fib(long n) {        
		if(n<0)            
			throw new RuntimeException("下标错误,应从0开始!");       
		if (n == 0)            
			return 0;        
		if (n == 1)            
			return 1;        
		long prePre = 0;       
		long pre = 1;      
		long result = 1;        
		for (long i = 2; i <= n; i++) {            
			result = prePre + pre;   //F(n)=F(n-1)+F(n-2)            
			prePre = pre;            //更新F(n-2)
			pre = result;        	//更新F(n-1)
		}        
		return result;    }         
	public void main(String[] args) {        
	}	
}

思路二
时间复杂度为O(logn)的解法

斐波那契数列有以下公式(可由数学归纳法推导得到):
在这里插入图片描述
由上式可知,求f(n),只需要对矩阵求(n-1)次方即可,但此时时间复杂度仍为O(n)。利用乘方的性质
在这里插入图片描述
利用递归的思路计算乘方,即可将时间复杂度降低为O(longn)。这里给出对乘方函数的递归代码(引用):

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;
}

矩形覆盖问题

题目描述:
用n个21的小矩形无重叠地覆盖一个2n的大矩形,总共有多少种方法?
  当n = 1时,有一种方法。
  当n = 2时,有两种方法。
  当n >= 3时,和斐波那契数列类似。第一步竖着放,有f(n-1)种方法;第一步横着放,有f(n-2)种方法。所以f(n)=f(n-1)+f(n-2)。

总结:

1、求n次方时,可以利用递归来降低时间复杂度;
2、斐波那契数列的实际问题扩展

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值