LeetCode 題解 | 198.打家劫舍
198.打家劫舍
打家劫舍 - 力扣(LeetCode)leetcode-cn.com
題目描述
你是一個專業的小偷,計劃偷竊沿街的房屋。每間房內都藏有一定的現金,影響你偷竊的唯一制約因素就是相鄰的房屋裝有相互連通的防盜系統,如果兩間相鄰的房屋在同一晚上被小偷闖入,系統會自動報警。
給定一個代表每個房屋存放金額的非負整數數組,計算你在 不觸動警報裝置的情況下,能夠偷竊到的最高金額。
示例 1:
輸入: [1,2,3,1]
輸出: 4
解釋: 偷竊 1 號房屋 (金額 = 1) ,然後偷竊 3 號房屋 (金額 = 3)。
偷竊到的最高金額 = 1 + 3 = 4 。
示例 2:
輸入: [2,7,9,3,1]
輸出: 12
解釋: 偷竊 1 號房屋 (金額 = 2), 偷竊 3 號房屋 (金額 = 9),接着偷竊 5 號房屋 (金額 = 1)。
偷竊到的最高金額 = 2 + 9 + 1 = 12 。
解決方案
根據這道題的條件特點:
如果兩間相鄰的房屋在同一晚上被小偷闖入,系統會自動報警(即相鄰的數字不能同時作爲最終求和的有效數字)。
分析
這個條件如果精簡掉其他內容,很容易讓人聯想到奇偶數。這個解法就是從這點出發。
- 設置兩個變量,
sumOdd
和sumEven
分別對數組的奇數和偶數元素求和。 - 最後比較這兩個和誰更大,誰就是最優解。
至少在下面這個例子裏,這麼做是成功的了。
接下來要解決的就是最優解不是純奇數和或者偶數和的情況。
這種情況下,最優解可能前半段出現在這邊,後半段出現在另一邊。那麼只要找到一個時機,當這一段的最優解沒有另一邊好時,就複製對面的最優解過來。
舉個例子:
當偶數和(奇偶指的數組下標)加到第二個 1 之後,發現還不如奇數和一個 3 大,就應該將對面的3複製過來替換掉自己的 2。
繼續計算後得到最優解。
思路
- 設置兩個變量,
sumOdd
和sumEven
分別對數組的奇數和偶數元素求和。 - 遍歷數組,索引爲奇數時,將元素加到奇數和,並與偶數和比較更新成max。
- 偶數和同理。
- 返回時進行最後一次更新max。
C++ 實現
int rob(vector<int>& nums)
{
int sumOdd = 0;
int sumEven = 0;
for (int i = 0; i < nums.size(); i++)
{
if (i % 2 == 0)
{
sumEven += nums[i];
sumEven = max(sumOdd, sumEven);
}
else
{
sumOdd += nums[i];
sumOdd = max(sumOdd, sumEven);
}
}
return max(sumOdd, sumEven);
}