演算法之動態規劃(二) 爬樓梯與搶房子

2021-09-30 20:05:57 字數 1727 閱讀 6686

假設你正在爬樓梯。需要 爬n 階你才能到達樓頂。每次你可以爬 1 或 2 個台階。你有多少種不同的方法可以爬到樓頂?

思路分析:從動態規劃的角度,這個問題的關鍵在於找出能夠推出結果的乙個「狀態」,每一步的「狀態」都可以由之前的「狀態」鎖推出。由於每一步可以爬1或2個台階,那麼,我到達第n(n>2)階,第一種可能就是我從第n-2階爬了兩層到的,第二種可能就是我從n-1階爬了一層到的——也就是說,到達第n階的方法可以拆分為到達第n-1階的方法數加上到達第n-2階的方法數,即

p(n) = p(n-1) + p(n-2)  

從而就提取出了當前「狀態」與之前「狀態」的乙個關係式,那麼求解的過程就很簡單了。

public class solution 

int dp = new int[n + 1];

dp[1] = 1;

dp[2] = 2;

for (int i = 3; i <= n; i++)

return dp[n];

}}

以上的時間複雜度和空間複雜度分別為o(n)、o(n)。

public class solution 

int first = 1;

int second = 2;

for (int i = 3; i <= n; i++)

return second;

}}

此時時間複雜度不變仍然為o(n),而空間複雜度降低到了o(1),因為只用到了三個變數。

你是乙個專業的小偷,計畫偷竊沿街的房屋。每間房內都藏有一定的現金,影響你偷竊的唯一制約因素就是相鄰的房屋裝有相互連通的防盜系統,如果兩間相鄰的房屋在同一晚上被小偷闖入,系統會自動報警

給定乙個代表每個房屋存放金額的非負整數陣列,計算你在不觸動警報裝置的情況下,能夠偷竊到的最高金額。

思路分析:可以把這個問題抽象成數學問題:在乙個非負整數陣列中拿取元素,要求不可以拿相鄰的元素,求能取得元素的和的最大值。  考慮當進行到第i個元素時,能夠獲得的錢數有兩f種可能:第一就是我搶了第i-1個,於是不能再搶第i個了,設此時獲得的錢是p(i-1);第二個可能就是我並沒有搶第i-1個房子,所以我可以搶第i個房子,那麼這個方法獲得的錢最多為p(i-2) + m(i),p(i-2)和m(i)分別為進行到第i-2個房子時能獲得的最大錢數(注意,進行到第i-2個房子,不一定是搶了第i-2個房子)和第i個房中存在的錢數。    以上的兩種可能,我們要取較大的那個,即

p(i) = max(p(i-1),p(i-2)+m(i)) 

從而我們得到了當前狀態與之前狀態的乙個關係式,從而進行求解。

class solution 

return best[n-1];

}}

在迴圈迭代的時候,可以使用與爬樓梯解法類似的優化方案對空間複雜度進行優化。

仍然是相同的條件,只有一點不同,就是要搶的房子並不是沿著街橫向排列,而是最後形成了乙個環。

思路:遵循著原來沿街排列的思路,只要把圓環相接處處理好就可以解決。

我們考慮任選一點i,如果搶了i,那麼i-1則不能搶;如果不搶i,則i-1就可以搶。

那麼我們可以從i和i-1之間將圓環截斷,最後求以下兩種情況的最大值: 如果搶i,那麼則將i-1從陣列裡刪除;如果不搶i,即從陣列中刪除i,而保留i-1。  通過這樣的方法,就可以將不易解決的圓環問題變成了兩個我們已經解決的普通的搶房子問題了。

演算法之動態規劃(爬樓梯)

通過把原問題分解為相對簡單的子問題的方式求解複雜問題的方法。動態規劃常常適用於有重疊子問題和最優子結構性質的問題。若要解乙個給定問題,我們需要解其不同部分 即子問題 再合併子問題的解以得出原問題的解。通常許多子問題非常相似,為此動態規劃法試圖僅僅解決每個子問題一次,從而減少計算量 一旦某個給定子問題...

動態規劃 爬樓梯

假設你正在爬樓梯,需要n步你才能到達頂部。但每次你只能爬一步或者兩步,你能有多少種不同的方法爬到樓頂部?比如n 3,1 1 1 1 2 2 1 3,共有3種不同的方法 返回 3 解題思路 沒接觸過動態規劃的時候,我用排列組合做的,在我這篇部落格中 可以看一下。實際上,這個題目就是乙個斐波那契數列,這...

爬樓梯 動態規劃

假設你正在爬樓梯。需要 n 階你才能到達樓頂。每次你可以爬 1 或 2 個台階。你有多少種不同的方法可以爬到樓頂呢?注意 給定 n 是乙個正整數。示例 1 輸入 2 輸出 2 解釋 有兩種方法可以爬到樓頂。1.1 階 1 階 2.2 階 示例 2 輸入 3 輸出 3 解釋 有三種方法可以爬到樓頂。1...