題目鏈接
tag:
- Easy;
- DP;
question:
??You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security system connected and it will automatically contact the police if two adjacent houses were broken into on the same night.
Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police.
Example 1:
Input: [1,2,3,1]
Output: 4
Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3).
Total amount you can rob = 1 + 3 = 4.
Example 2:
Input: [2,7,9,3,1]
Output: 12
Explanation: Rob house 1 (money = 2), rob house 3 (money = 9) and rob house 5 (money = 1).
Total amount you can rob = 2 + 9 + 1 = 12.
思路:
??這道題的本質相當于在一列數組中取出一個或多個不相鄰數,使其和最大。那么我們對于這類求極值的問題首先考慮動態規劃Dynamic Programming
來解,我們維護一個一位數組dp,其中dp[i]表示到i位置時不相鄰數能形成的最大和,那么狀態轉移方程怎么寫呢,我們先拿一個簡單的例子來分析一下,比如說nums為{3, 2, 1, 5},那么我們來看我們的dp數組應該是什么樣的,首先dp[0]=3沒啥疑問,再看dp[1]是多少呢,由于3比2大,所以我們搶第一個房子的3,當前房子的2不搶,所以dp[1]=3,那么再來看dp[2],由于不能搶相鄰的,所以我們可以用再前面的一個的dp值加上當前的房間值,和當前房間的前面一個dp值比較,取較大值當做當前dp值,所以我們可以得到狀態轉移方程dp[i] = max(num[i] + dp[i - 2], dp[i - 1])
, 由此看出我們需要初始化dp[0]和dp[1],其中dp[0]即為num[0],dp[1]此時應該為max(num[0], num[1]),代碼如下:
// DP
class Solution {
public:
int rob(vector<int> &num) {
if (num.size() <= 1)
return num.empty() ? 0 : num[0];
vector<int> dp = {num[0], max(num[0], num[1])};
for (int i=2; i<num.size(); ++i)
dp.push_back(max(num[i] + dp[i-2], dp[i-1]));
return dp.back();
}
};