编程题_剑指offer10_斐波那契数列

1 题目

leetcode
写一个函数,输入n,求斐波那契数列的第n项。斐波那契书写的定义如下:
F(0)=0,F(1)=1
F(N)=F(N-1)+F(N-2),其中N>1
斐波那契数列由0和1开始,之后的斐波那契数列就是由之前的两数相加而得出。
答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。

2 解

2.1 超时解

    public int fib(int n) {
        return (int) (recursive(n)%(1e9+7));
    }

    public int recursive(int n){
        if(n==0)
    		return 0;
    	if(n==1)
    		return 1;
    	
    	return recursive(n-1)+recursive(n-2);
    }

直接使用递归求解,当要求的数字较大时,结果会超出时间限制。

2.2 优化后的递归

直接使用递归求解超时是因为由很多重复的计算,可以引入一个Map存储已经算出的结果,提高运行效率。最终代码如下

    public int fib(int n) {
    	Map<Integer,Integer> map=new HashMap<Integer, Integer>();
    	map.put(0,  0);
    	map.put(1,  1);
        return (recursive(n,map));
    }

    public int recursive(int n, Map<Integer, Integer> map){
    	if(n==0)
    		return 0;
    	if(n==1)
    		return 1;
    	//是否有 n-1的值
    	if (!map.containsKey(n-1)) {
    		//计算并放入
			map.put(n-1,  recursive(n-1, map));
		}
    	if (!map.containsKey(n-2)) {
    		//计算并放入
			map.put(n-2, recursive(n-2, map));
		}
    	
    	return (map.get(n-1)+map.get(n-2))%(1000000007);
    }

2.2.1 求解遇到的错误

在优化的过程中遇到了一些错误,记录一下。
首先是测试用例27,输入48,预期值与输出值差距过大,调试发现是值越界导致变成了负数,所以改成了long型存储。
然后是测试用例41,输入81,预期值与输出值仅差2,百度发现取模时应该写成数字1000000007,修改后通过。
然后是测试用例47,输入95,输出值变成负数了,毫无疑问是越界了。long型也无法存储的话,只能在存储进map之前就进行取模了,修改后通过。
最后尝试着将所有数据都使用int型存储,也通过了。

3 其它解

3.1 循环求解

利用循环自底向上求解,可以防止重复计算。

    public int fib(int n) {
		int a=0,b=1,sum;
		for (int i = 0; i < n; i++) {
			sum=(a+b)%(1000000007);
			a=b;
			b=sum;
		}
		return a;
    }

4 参考链接

1.如何以1e9+7取模?
2.精选解


2020.09.07更新
新的递归代码,从青蛙跳台阶的一个解中看到的,青蛙跳台阶和斐波那契数列区别在于起始值的不同,解法类似。

    public int fib(int n) {
    	Map<Integer,Integer> map=new HashMap<Integer, Integer>();
    	map.put(0,  0);
    	map.put(1,  1);
        return (recursive(n,map));
    }

    public int recursive(int n, Map<Integer, Integer> map){
    	if(map.containsKey(n)) {
    		return map.get(n);
    	}else {
    		map.put(n, (recursive(n-1, map)+recursive(n-2, map))%(1000000007));
    		return map.get(n);
    	}
    }

参考链接:递归法优化

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值