LeetCode 198 打家劫舍

链接:https://leetcode-cn.com/problems/house-robber

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。

给定一个代表每个房屋存放金额的非负整数数组,计算你在不触动警报装置的情况下,能够偷窃到的最高金额。

示例 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 。

这道题是一道动态规划题,首先动态规划题我们要明确它的状态表示,这道题的状态表示的特殊之处是,我们使用了两个数组。

令f[i]表示在前i个数中选,所有不选nums[i]的选法的最大值。

令g[i]表示在前i个数中选,所有选择nums[i]的选法的最大值。

因为如果第i个数不选的话,那么第i-1个数,选也行,不选也行。所以 f[i] = max(f[i - 1] , g[i - 1])

而如果选了第i个数,那么第i-1个数一定不能选。所以g[i] = f[i - 1] + nums[i]

最终的结果是max(f[n- 1] , g[n - 1])

c++代码如下:

 1 class Solution {
 2 public:
 3     int rob(vector<int>& nums) {
 4         int n = nums.size();
 5         vector<int> f(n + 1), g(n + 1);
 6         f[0] = 0, g[0] = 0;
 7         
 8         for(int i = 1; i <= n; i++){
 9             f[i] = max(f[i-1], g[i-1]);
10             g[i] = f[i-1] + nums[i-1];
11         }
12         return max(f[n], g[n]);
13     }
14 };

因为在上面的代码中,其实对于两个数组,每个数组都只用到了两个状态,f[i-1],f[i],g[i-1],g[i],所以可以将数组简化为四个变量来表示。

 1 class Solution {
 2 public:
 3     int rob(vector<int>& nums) {
 4         int n = nums.size();     
 5         int f, g, f_last = 0, g_last = 0;
 6         for(int i = 0; i < n; i++){
 7             f = max(f_last, g_last);
 8             g = f_last + nums[i];
 9             f_last = f;
10             g_last = g;
11         }
12         return max(f_last, g_last);
13     }
14 };

猜你喜欢

转载自www.cnblogs.com/hellosnow/p/12301731.html