滾動數組
首先什么是滾動數組呢?就是將一個可能有100元素的遍歷,我用一個size=2的數組去遍歷,這時你可能會問容量為3的數組大小明明小於100啊,為什么可以拿他去遍歷100個元素呢?
這時我會用一句話回答你:“具體問題具體分析!”,你有沒有想過,如果我遍歷過的元素就再也不會使用他了,那我是不是可以將這個元素丟棄呢?
所以滾動數組常常用於解決遞推問題,我在上一章就說過:“遞推數組的核心思想就是數學歸納法,而數學歸納法的第二步就是通過前一個狀態的運算得到當前狀態”,那么假設我第十個狀態的結果只要知道第九個狀態的具體情況,那我還需要第一個,第二個,第三個。。。。狀態的情況呢?是不是不需要了,那就可以舍棄掉了,這是滾動數組就派上用場了。
中上,如果問題的解決對於子問題的答案並不需要進行存儲,那么就可以利用滾動數組的思想解決問題,更加的節省空間。
滾動數組的核心:取余
我見過的所有使用滾動數組的技巧就是取余,這樣不管遍歷到多大的下標值,你都可以一個小的下標值進行表示,讓新的答案覆蓋掉原來舊的答案。
舉個例子
對於斐波那契數列F[n] = F[n - 1] + F[n - 2]有兩種寫法;
普通的寫法:
void func1()
{
int d[101] = {0};
d[0] = 1;
d[1] = 1;
for (int i = 2; i < 100; i++)
{
d[i] = d[i - 1] + d[i - 2];
}
printf("%d", d[99]);
}
滾動數組方式的寫法:
void func2()
{
int d[3];
d[0] = 1;
d[1] = 1;
for (int i = 0; i < 100; i++)
{
d[i % 3] = d[(i - 1) % 3] + d[(i - 2) % 3];
}
printf("%d", d[99 % 3]);
}
DP
對於二維數組也可以用滾動數組的方式解決:計算二維數組每一位的值等於它的上面的值和左邊的值的和。
int d[100][100];
for(int i = 100;i<100;i++){
for(int j = 0;j<100;j++){
d[i][j] = d[i-1][j]+d[i][j-1];
}
}
而運用滾動數組,寫法就是
int d[2][100];
for(int i = 0;i<100;i++){
for(int j = 0;j<100;j++){
d[i%2][j] = d[(i-1)%2][j]+d[i%2][j-1];
}
}
運用滾動數組的寫法比普通的遞推寫法更節省空間優勢,但是在時間復雜度上面並沒有什么優勢。
好的,先知道了滾動數組,我們就可以運用滾動數組解決下面的動態規划問題了。