動態規划之滾動數組


滾動數組

首先什么是滾動數組呢?就是將一個可能有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];
}
}

運用滾動數組的寫法比普通的遞推寫法更節省空間優勢,但是在時間復雜度上面並沒有什么優勢。

好的,先知道了滾動數組,我們就可以運用滾動數組解決下面的動態規划問題了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM