滚动数组的使用:
使用有限个位置储存元素的信息,这有限个位置相当于一个空间复杂度为O(1)的vector,每次最后一个位置放入新加入的元素,其余元素向前移动一个位置。
在每一个子问题中,dp[i]只依赖于O(1)有限个状态转移而来,那么就可以用滚动数组使空间复杂度由O(N)降为O(1)。
比如斐波那契数列:
如果用一维数组vector<int> dp储存状态,空间复杂度就是O(n)。因为存放了n个元素各自的斐波那契数。
dp[i]=dp[i-1]+dp[i-2],
注意到dp[i] 只依赖于dp[i-1]和dp[i-2]两个状态,而不依赖之前dp[i-3],dp[i-4]...之类的状态,换句话说,当我们处理到dp[i]时,我们无需记录dp[i-3] dp[i-4]的状态。
所以可以用两个变量p,q代表dp[i-2],dp[i-1],用r代表当前处理的dp[i],r=p+q,即相当于dp[i]=dp[i-2]+dp[i-1],然后下一次循环,让p=q,q=r,意思是数组向p的方向滚动了一位,滚动数组里原来的dp[i-2]变成dp[i-1],原来的dp[i-1]变成dp[i],r变成dp[i+1]~~
class Solution {
public:
int fib(int n) {
if (n < 2) {
return n;
}
int p = 0, q = 0, r = 1;
for (int i = 2; i <= n; ++i) {
p = q;
q = r;
r = (p + q);
}
return r;
}
};