乙個小偷的自我修養

2021-10-25 05:58:52 字數 2221 閱讀 5437

總結這週的leetcode,遇到了乙個有意思的題目,名字叫打家劫舍。題目的意思是讓你幫小偷規劃偷竊的路線,是一道動態規劃的題目。由於之前沒有接觸過動態規劃演算法,所以在這道題上花了很多的時間,藉此文章總結一下。

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

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

示例1:

輸入:nums=[1,2,3,1]

輸出:4

解釋:偷竊 1 號房屋 (金額 = 1) ,然後偷竊 3 號房屋 (金額 = 3)。

偷竊到的最高金額 = 1 + 3 = 4 。

一開始面對這個問題時,我的想法是這樣的:

題目要求的是竊取到的總金額最多,那麼我可以將所有房間的金錢都遍歷一遍,每次偷取能夠偷取的房間中金額最高的那間房,並且偷竊後將其標記為偷過的房間,之後迴圈這樣的過程,直到沒有房間可以偷。演算法的步驟是這樣的:

step 1:遍歷陣列。

step2:找到陣列中金錢最大的那間房,然後判斷是否能偷,即判斷相鄰的房間是否被偷過。

step3:若能偷,則偷,將房間的錢計入偷到的金錢總數中,並且將其標記為偷過的房間;若不能偷則將其標記為不能偷的房間。

step4:迴圈上述過程,直到所有房間都被標記完畢。

step5:返回偷到的金錢總數。

在仔細思考過後,我發現這個解法是有問題的。通過這個解法,你只能找出乙個排序中數字最大的序列,但是能偷到的金額數不一定是最高的。假設屬組中有幾個重複的比較大的金額的房間時,就會出現問題。

例如:輸入[1,4,5,4,1]

按照上述演算法,其能夠偷竊到的最高金額是6。但假設小偷先偷金額數為4的房間,其能夠偷竊到的最高金額是8。可見第乙個解法是有問題的。

基於遇到問題,自己沒思路就要懂得抱大腿的方**指引下,我去看了leetcode官方解答。官方解答應用了一種動態規劃的演算法。

動態規劃,我的理解就是走一步看一步,後邊的狀態由前面的乙個或幾個狀態來決定。具體地解釋我想引用一下我之前看的某篇部落格:

六大演算法之三:動態規劃

基於我們這個題目而言,我們可以由最簡單的情況開始推理:

1.當沒有房子時,小偷當然一分錢也偷不到,能偷到的金錢總數為0。

2.當只有乙個房子時,小偷沒有選擇,能偷到的金錢總數就是當前房子所存的金錢數。

3.當有兩個房子時,小偷可以選擇偷或是不偷第二個房子。

如果偷了第二個房子,就不能偷第乙個房子,小偷能偷到的金錢總數就是第二個房子的金錢數加上第0個房子能偷到的最大的金錢總數,當然第0個房子不存在,所以金錢數為0,小偷能偷到的金錢總數就是第二個房子的金錢數。

如果沒偷第二個房子,小偷能偷到的金錢總數就是第乙個房子能偷到的最大的金錢總數。

最終小偷能偷到的最大的金錢數就是前面兩種情況中,能偷到的金錢總數更大的那個。

4.這裡可以歸納下,假設當前小偷已經偷到第i個房子(第i間房還沒決定要不要偷),偷到的金錢數為dp[i-2],這時再加一間房子,小偷現在面臨兩個選擇:

1.偷第i間房子。此時小偷就不能偷第i-1間房子,此時,小偷能偷到的最大金錢總數為:

dp[i]=dp[i-2]+nums[i];

2.不偷第i間房子。此時,小偷能偷到的最大金錢總數為小偷偷前i-1間房子所能偷到的最大金錢數:

dp[i]=dp[i-1];

3.最終小偷能偷到的金錢總數為:上面兩種選擇中能偷到的金錢數更大的那個。

通過上文解釋的動態規劃演算法,我們可以不用考慮全域性,而是通過前乙個或幾個狀態來決定當前的狀態,直到走到結束的狀態。對於本題的當前狀態dp[i]是由dp[i-2]和nums[i],以及 dp[i-1]決定。所以,**中我用first來存dp[i-2],用second來存dp[i-1]和dp[i-2]+nums[i]中較大的那乙個。

c++**實現如下:

class

solution

if(length==2)

if(length>2)

return second;

}else}}

;

這是我第一次接觸動態規劃演算法,感覺動態規劃演算法,在解決規模為n的問題,並且當前狀態由之前的乙個或幾個狀態決定,同時之前的狀態不由之後的狀態影響的問題時,具有一定的優勢。通過這次總結,希望自己在之後遇到類似的問題時,能夠想起這個演算法。本篇文章的**和演算法還有可以優化的部分,時間關係就沒有優化了,之後有時間再看,溜了,溜了~

乙個SEMer的自我修養

標題創意來自周星星電影裡的那本 乙個演員的自我修養 只見其名不看其書。作為80後,很多朋友都是看星爺的 長大的 作為semer,希望也有很多朋友能看我的部落格成長。好吧,我膨脹了,這是不對的。semer的自我修養裡就不包括這一條。當別的剛入門的semer在各大論壇各個qq群問為什麼怎麼做好的時候,你...

乙個程式設計師的自我修養

一 前提 1 一切都是為了生活,這是本!2 人生時刻要未雨綢繆。3 本人是嵌入式偏軟體方向的工程師,電腦是必須天天面對的。4 所在的辦公室,天天吹空調。5 這樣的環境下,就會面對可能會出現的兩個問題,一是 問題,二是可能的脫髮問題。二 分析 1 影響 的因素有,顯示屏,空調,飲食,運動,護理。2 影...

乙個程式設計師的自我修養

本文是以個人為基點闡述的 主要以個人素質和發展方向為主 本文主要說四個內容 學習能力 時間轉換能力 需求轉換能力 技術能力 按照先後順序 分別說一下 學習能力 第二 時間轉換能力 這個時間的概念 有些人可能會理解錯誤 有人可能會認為說的是我們開發某一產品的時間 當然 你這個概念也是包含在我要說的時間...