济南seo网站建站,外贸推广用中文网站,正规网站建设学习网公司哪家好,wordpress自动推送百度兔子繁殖问题#xff1a; 这是一个有趣的古典数学问题#xff0c;著名意大利数学家Fibonacci曾提出一个问题#xff1a;有一对小兔子#xff0c;从出生后第3个月起每个月都生一对兔子。小兔子长到第3个月后每个月又生一对兔子。按此规律#xff0c;假设没有兔子死亡…兔子繁殖问题 这是一个有趣的古典数学问题著名意大利数学家Fibonacci曾提出一个问题有一对小兔子从出生后第3个月起每个月都生一对兔子。小兔子长到第3个月后每个月又生一对兔子。按此规律假设没有兔子死亡第一个月有一对刚出生的小兔子问第n个月有多少对兔子
相信上面的题目稍微有点经验的程序员都了解过这就是著名的斐波那契数列Fibonacci sequence该数列又称黄金分割数列、因数学家列昂纳多·斐波那契Leonardoda Fibonacci以兔子繁殖为例子而引入故又称为“兔子数列”指的是这样一个数列1、1、2、3、5、8、13、21、34、…… 特点这个数列从第3项开始每一项都等于前两项之和。
表达式F[n]F[n-1]F[n-2] (n2,F[0]0,F[1]1)
看到这个表达式相信大多数读者都能想到使用递归算法实现那么由此我们可以得到求解斐波那契数列的一种算法
public class Main {public static int f (int n) {if (n 2) {return 1;} else {return f(n-1) f(n-2);}}public static void main(String[] args) {int n 12;System.out.println(f(n));}
}
注若用于求解兔子繁殖问题需要对输入参数进行额外处理
但是 对于小数据来说上面的算法或许还可行但是我们发现用30作为输入进行计算的时候程序输出结果时已经有了一定的时间延迟而用再大的数据来测试就会发现结果在短时间内根本出不来这是为什么呢 对于上面的递归求解方法来说时间复杂度为O(2^n)所以效率非常慢为了计算一个f(n)需要存在一个f(n-1)和一个f(n-2)然而f(n-1)递归地对f(n-2)h和f(n-3)进行调用因此存在两个单独计算f(n-2)的调用。继续跟踪整个算法会发现f(n-3)被计算了3次f(n-4)被计算了5次而f(n-5)则是8次。冗余的计算无疑加重了编译器的负担如果编译器不能对之前计算过的数据进行保留这样的增长就无法比避免。 所以这里给出第二种算法,时间复杂度为O(n)
public class Main {public static int f (int n) {if (n 2) {return 1;}int last 1;int nextToLast 1;int answer 1;//前2位都为1for (int i 3; i n; i) {answer last nextToLast;nextToLast last;last answer;}return answer;}public static void main(String[] args) {int n 12;System.out.println(f(n));}
}
第二种算法即使用非常大的数据进行测试也仅仅是稍有延迟短时间内基本可以输出。
下面我们来分析一下这两种算法的思想
分治策略是对于一个规模为n的问题若该问题可以容易地解决比如说规模n较小则直接解决否则将其分解为k个规模较小的子问题这些子问题互相独立且与原问题形式相同递归地解这些子问题然后将各子问题的解合并得到原问题的解。 提到分治策略就不得不提递归递归与分治的关系网上说的有诸多含糊不清愚见分治是一种思想而递归是实现分治思想的方法。
动态规划的基本思想与分治策略类似区别就在于动态规划是一种带基于记忆化搜素的思想这也是不同于普通搜索算法的一大特点。 所以动态规划思想常用于解决问题中含有较多重叠子的问题这种问题应尽量避免使用单纯的递归算法实现。