2020.05.29
你是乙個專業的小偷,計畫偷竊沿街的房屋。每間房內都藏有一定的現金,影響你偷竊的唯一制約因素就是相鄰的房屋裝有相互連通的防盜系統,如果兩間相鄰的房屋在同一晚上被小偷闖入,系統會自動報警。
給定乙個代表每個房屋存放金額的非負整數陣列,計算你在不觸動警報裝置的情況下 ,一夜之內能夠偷竊到的最高金額。
第n家123
4家中錢數32
611. 先把大佬@lkaruga的**悄悄貼上來——
class solution
else
}return max(sumodd, sumeven); //返回奇或偶出發點中的最大值即可
};};
分兩種初始情況討論——前兩所房子中,偷1或者偷2。其他地方都還蠻好理解的,備註1部分是大佬思路裡比較巧妙有趣的地方。簡單來說,這兩行備註1部分的**就是為了解決這樣的問題——不一定要所有房子間隔為1時才能偷到最多,在一些特定情況下,間隔可能是2。(間隔不會是3、4等更大的數字,因為間隔a、b、c這3間房子的話,b房間是可以去搶的,多多益善。)
e.g. 輸入:[2,1,2,1,1,100]
錯誤輸出1:5(2+2+1)
錯誤輸出2:102(1+1+100)
正確輸出:104(2+2+100)
區別於正常邏輯理解裡只有讓陣列下標相差2才是實現間隔2的唯一方式,作者意識到間隔數是幾的根源在於舊有奇偶形制是否發生了變化,即,若保持了1、3、5、7或2、4、6、8的單奇數或單偶數形制,間隔就會是1;而倘若發生一次跳換,例如1、3、6、8,那麼在跳換奇偶形制時,也就滿足了間隔變為2的情況。
為了應對這種情況,作者選擇了max()函式來間接實現跳換。
由於我們只需要求出最終偷到的最大錢數,所以任一流程步驟中,若已經被判定為非最優解,便可以將其用更優解覆蓋掉。於是在**中的備註1處,可以看到,在以偶數0為偷竊起點(偷第一所房子,房子編號為0)的每一次新偷錢數加和完成之後,都需要將此方案下的現有總錢數和以奇數1為偷竊起點的方案(不偷第一所房子,偷第二所,房子編號為1)中上一次的總錢數進行比較。若比較結果裡另一方案中上一次的總錢數還大一些,那麼直接繼承另一方案,完全抹掉本方案的舊值——實現跳換,房屋間隔數為2。
同理,以偷第二所房子開始的方案也實時需要和另一方案的舊值進行比較大小,隨時面臨著跳換的可能。
結合上例,該思路具體為:
房子編號01
2345
總錢數錢數21
211100
/從0偷起2-
4-5-
5
從1偷起-1
-2(2沒有大於4!)=> 4-
104104
啊怎麼樣,是不是非常巧妙呢(#^.^#)(狗頭)
2. 再來康康力扣官方的答案——
class solution
int size = nums.size();
if (size == 1)
int first = nums[0], second = max(nums[0], nums[1]); //備註2:開始遞迴了,下方文字詳述
for (int i = 2; i < size; i++)
return second;
}};
怎麼說呢,這個思路其實也非常非常符合正常理解,估計老手都不用動腦子,直接上來就能寫叭~ 所以作為歸納分類的前件,size = 0 和size = 1的情況不作解釋咯,直接可以看**中的注釋。
備註2部分的邏輯梳理是這樣的——
當進行到第n個房子時,在安全不被抓的情況下,我是偷呢?還是不偷呢?
當然看偷的錢多還是不偷的錢多了!!這時就有小白(比如我)會問:這不傻帽兒嗎?反正安全,當然是進去偷的錢多啦!不偷,賺0元;偷,起碼有1w。
其實非也。我們需要注意的是,偷或不偷還會影響對下一棟房子進行偷竊的安全係數。如果你因為這次偷竊是安全的就狠下**,那麼下一棟房子裡縱然是有100w也只能跳過了(ಥ﹏ಥ)。所以這種在當前安全的情況下「偷或不偷」的分類方式是合理的,且也巧妙地分離了間隔為1和2的情況(^-^)。
好的,現在只需要確定「偷或不偷」的判定標準就可以啦!
於是我們華麗引出「動態規劃」的概念。鏘鏘鏘鏘~我們運用了遞迴的思想來寫這個判定公式。由之前的**,我們已知n<=2時的情況,那麼問題來了,比如n=3時,這第三間房子偷不偷?安全的情況下,偷,總錢數就是nums[0] + nums[2] , 不偷,總錢數就是nums[0] ;不安全的情況下當然不能偷,總錢數就是nums[1]。
開始公式推導。
偷第一間房子時最多獲得錢數mostmoney[ 0 ] = nums[ 0 ] ,
到第二間時最多獲得的錢數mostmoney[ 1 ] = max ( nums[0] , nums[1] );
到第三間時最多獲得的錢數mostmoney[ 2 ] = max ( mostmoney[ 1 ] , mostmoney[ 0 ] + nums[ 2 ] );
遞迴公式可寫為:mostmoney[ i ] = max ( mostmoney[ i - 1 ] , mostmoney[ i - 2 ] + nums[ i ] )
在上面的**中,標答使用了滾動陣列,用temp臨時陣列實現了僅用三個儲存位的o(1)空間複雜度;力扣也給出了完全儲存此遞迴的陣列迴圈寫法:
for (int i = 2; i < size; i++)
動態規劃——將大問題分解成子問題。
實現方式:
1.自底向上解決完最末層的所有子問題之後,再往上一層迭代。自底向上的乙個經典實現是斐波那楔數列的遞推實現,即f[i] = f[i - 1] + f[i - 2] 。
2.自頂向下也即記憶化搜尋。從問題的最終狀態出發,一般採用遞迴的方法實現。
打家劫舍 力扣 LeetCode
你是乙個專業的小偷,計畫偷竊沿街的房屋。每間房內都藏有一定的現金,影響你偷竊的唯一制約因素就是相鄰的房屋裝有相互連通的防盜系統,如果兩間相鄰的房屋在同一晚上被小偷闖入,系統會自動報警。給定乙個代表每個房屋存放金額的非負整數陣列,計算你在不觸動警報裝置的情況下,能夠偷竊到的最高金額。示例 1 輸入 1...
力扣解題思路 打家劫舍
思路 題目 你是乙個專業的小偷,計畫偷竊沿街的房屋,每間房內都藏有一定的現金。這個地方所有的房屋都圍成一圈,這意味著第乙個房屋和最後乙個房屋是緊挨著的。同時,相鄰的房屋裝有相互連通的防盜系統,如果兩間相鄰的房屋在同一晚上被小偷闖入,系統會自動報警。給定乙個代表每個房屋存放金額的非負整數陣列,計算你在...
2020 8 4 力扣每日
儲存0入度元素 14for int i 0 i numcourses i 18while queue.isempty 26 27return count numcourses 判斷拓撲排序元素個數是否與課程數一致28 29 解題思路 根據題目中先修課程的描述,其與有向圖的構造類似,而判斷最終是否可以...