先上题目:
小时候我们都跳过方格游戏吧!现在规定一次只能向前跳1格或2格,不能后退,要想正好跳到第10格,有多少种跳法?
一、暴力枚举
程序我就不写了,因为嵌套循环太多,时间复杂度高。
二、我们假设跳到n格有F(n)种可能;
我们来思考,我跳一次有几种可能,很简单,跳一次我有2种可能,1格或者2格;同理,我最后一次跳到第n格有几种可能?当然2种,比如我跳一次到第5个格的可能有从4格跳到5格或从3个跳到5格2种可能,而总的方法就等于跳到第4格和跳到第3格方法的总和。
其实上面是一种递归的思想;F(10) = F(9) + F(8) F(9) = F(8) + F(7) ...........
即F(n) = F(n-1) + F(n-2)
所以我们可以用递归实现:
三、第二方法中的时间复杂度为O(2^n),仔细分析复杂度高是因为在递归时重复了一些值的运算,导致时间复杂度的增加;所以为了减少重复计算,我们建立一个备忘录来记录已经计算过的值,则时间复杂度变为O(n),但空间复杂度为O(n);int GetNum(int n) { if(n==1) return 1; if(n==2) return 2; return (GetNum(n-1) + GetNum(n-2)); }
四、那有没有更好的办法,让空间复杂度更低,甚至为O(1)呢?哈哈 下面就是今天的重点,动态规划!int GetNum(int n) { if(n==1) return 1; if(n==2) return 2; if(map.text(n)) { return map.get(n); }else { int Value=(GetNum(n-1) + GetNum(n-2)); map.put(n,Value); return Value } }
我们不妨把思路逆过来!这样我们走到第n格就只依赖于n-1和n-2格的方法,所以我们只要保持前2个状态的方法就可以迭代出当前的方法。所以我们需要建立2个临时变量;这样增加2个变量反而空间复杂度变为O(1)了。
程序如下:
int GetNum(int n) { if(n==1) return 1; if(n==2) return 2; int a =1,b=2,temp=0,i; for(i = 3;i<=n; i++) { temp = a+b; a=b; b=temp; } }
这是对动态规划最基本的了解!要想真正测试自己懂了没,要看下一篇动态规划进阶篇,那道题会了才是真会了!