逛leetcode,对于面试题8.11.硬币问题一点思路都没有,答案都看不懂,感觉很受伤。决定花这个周末好好搞一下动态规划算法。
在b站上看到一个很适合入门的视频
https://www.bilibili.com/video/BV18x411V7fm
美中不足的是,没有代码。。。所以根据视频的思路补充Java和Python的解供大家配合食用。
斐波那契数列
1.递归解
java
public long fibRec(int n) {
// 如果1或者2 返回1 也是递归程序的出口
if (n==1 || n==2) {
return 1;
}
// 不然就返回前面两个数的和
return fibRec(n - 1) + fibRec(n - 2);
}
python
def fibRec(n):
if n == 1 or n == 2:
return 1
else:
return fibRec(n-1) + fibRec(n-2)
递归式写起来真的很简洁!但是它的时间复杂度是2^n,而且递归层数太多,直接有爆栈的危险!(这也告诉我们,递归写法往往不算是很成功的算法)
2.非递归
java
public long fibDp(int n) {
long [] fib = new long[n]; // 建立一个长度为n的数组
for (int i = 0; i < n; i++) {
// 如果序号为0或者1,则赋值为1
if (i <= 1 ) {
fib[i] = 1;
} else {
// 否则赋值为前面两个的和
fib[i] = fib[i-1] + fib[i-2];
}
}
return fib[n-1];
}
python
def fibDp(n):
fib = []
for i in range(n):
if i == 0 or i == 1:
fib.append(1)
else:
fib.append(fib[i-1] + fib[i-2])
return fib[n-1]
这个时间复杂度直接降到了n,如果用原来的递归法算fibo(100),直接就给你卡住不动了,这个算法算100也是秒出。(用java算100,long类型就hold不住了,类型换成double就可以了~)
这个思路在《数据结构与算法描述 java语言描述》里也有写到——用一个表代替递归。