牛客 動態規劃入門

2022-10-08 22:15:27 字數 1063 閱讀 8404

這似乎是乙個老生常談的題目:

在古老的年代,天地間誕生了乙個會自己增長的數列。大地賜予它生命,告訴它1為萬物之始。天空則傳授了它數列增長之道,告訴它永遠以前一刻的自己為基石,方可不斷超越自我,實現數列之永恆。於是這個數列就這樣開始了它艱辛的增長之路,1,1,2,3,5,8,13,21,34 ... 功夫不負有心人,終於有一天,乙個數學家發現了它,將它命名為fibonacci數列,並將這個數列的傳奇故事介紹給了世人。

所以,在座的程式設計師們,第n個數字是幾呢,請寫出你的** -_-

當我看到這個題目,第一反應是,就這?乙個遞迴不就搞定了

public

:

int fibonacci(int

n) else

}};

在牛客上一執行,確實通過了所有測試用例,但是執行時間也很嚇人,237ms !好傢伙 !

1)存在太多的重複計算,比如n=5,f(5)=f(4)+f(3),顯然這裡要算一次f(3),然後f(4)=f(3)+f(2),這裡又要算一次f(3),而類似的重複計算還有很多。n越大,整個遞迴樹就越大,重複計算就越多。

2)會出現遞迴的棧溢位,因為函式的呼叫是通過棧實現的。

這裡加一嘴,請原諒我的偏題:如果程式語言對尾遞迴有優化,我們將遞迴寫成尾遞迴可以避免棧溢位。什麼是尾遞迴呢,就是在函式返回的時候,呼叫函式本身,並且return語句不能包含表示式。所以...很遺憾的是j**a和python語言都未對尾遞迴做優化。但是python的話可以使用@tail_call_optimized這個裝飾器實現尾遞迴優化。另外再看看c++,我們只需在gcc後面加上-o2引數,就可以實現尾遞迴優化。

那麼如何使用動態規劃計算斐波那契數列呢,這是我的**

public

int fibonacci(int

n)

return dp[n-1];

}

大致就是,之前用遞迴,是乙個自頂向下的過程,比如n=5,我們是從5到1去推進。而這裡是乙個自底向上的過程,先計算n=1,n=2 ... 儲存到陣列裡,然後自然而然地算出n=5的情況,很顯然這樣有效避免了重複計算,也不需要使用遞迴。

動態規劃入門

1 用 dp 做的題大多數返回值是int boolean,求max min,不能打亂原來輸入順序。2 動態規劃有兩個重要定義,乙個叫 optimal substructure 另乙個叫 overlap subproblem 各種排序 tree 類問題中,都會用到 divide conquer 的思想...

動態規劃入門

大家可以看看這篇文章dp,哪個更容易理解就看哪個!一 動態規劃的定義 動態規劃程式設計是一種針對於解決最優化問題的一種途徑 一種方法,而不是一種特殊演算法,也就是說它沒有固定的模板。在動態規劃中,每走一步都要看看能不能最優,而且動態規劃最擅長的就是多階段問題!二 動態規劃的基本概和基本模型構成 1....

動態規劃入門

學動態規劃自然要從數字三角形開始起步,那麼我們就先從數字三角形開始。數字三角形題目 有乙個由非負整數組成的三角形,第一行只有乙個數,除了最下行之外的每個數的左下方和右下方各有乙個數,如下圖所示 3 24 10 1 4 3 2 20 從第一行的數開始,每次可以往下或往右下走一格,直到走到最下行,把沿途...