LeetCode刷题笔记-动态规划-day3

LeetCode刷题笔记-动态规划-day3

198. 打家劫舍

1.题目

原题链接:198. 打家劫舍

image-20220207094442765

2.解题思路

我们可以用f[i]表示小偷走到第i个房间偷的总金额,可以分两种情况:

  1. 小偷不选第i个房间的现金,那么f[i]=f[i-1];
  2. 小偷选择偷第i个房间的现金,因为不能选择连续的房间,所以f[i]=f[i-2]+nums[i];

如图:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-thAHvi6W-1644281720391)(https://gitee.com/llxpp/blog-image/raw/master/img/20220207100309.png)]

图转载:https://www.acwing.com/solution/content/19504/

3.代码

class Solution {
    
    
public:
    int rob(vector<int>& nums) {
    
    
        int n=nums.size();
        vector<int> f(n+1);
        if(n<2) return nums[0];
        f[0]=nums[0],f[1]=max(nums[0],nums[1]);
        for(int i=2;i<n;i++){
    
    
            f[i]=max(f[i-1],f[i-2]+nums[i]);
        }
        return f[n-1];
    }
};

213. 打家劫舍 II

1.题目

原题链接:213. 打家劫舍 II

image-20220207094507632

2.解题思路

从题意可知该题相比198. 打家劫舍只是多了一个条件:第一个房间和最后一个房间不能同时选,因此我们可以枚举这两种情况:

  1. 一定不选第一个,即求出[2,n]区间可以得到的最大价值
  2. 一定不选最后一个,即求出[1,n-1]区间可以得到的最大价值

最后取两种情况的最大值即可。

3.代码

class Solution {
    
    
public:
    int rob(vector<int>& nums) {
    
    
        int n=nums.size();
        vector<int> f(n+1);
        if(n<2) return nums[0];
        if(n==2) return max(nums[0],nums[1]);
        f[0]=nums[0],f[1]=max(nums[0],nums[1]);
        for(int i=2;i<n-1;i++){
    
    
            f[i]=max(f[i-1],f[i-2]+nums[i]);
        }
        int t1=f[n-2];
        f.clear();
        f[0]=0,f[1]=nums[1];
        for(int i=2;i<n;i++){
    
    
            f[i]=max(f[i-1],f[i-2]+nums[i]);
        }
        int t2=f[n-1];
        return max(t1,t2);
    }
};

740. 删除并获得点数

1.题目

原题链接:740. 删除并获得点数

image-20220207094532899

2.解题思路

仔细分析题目可知该题与198. 打家劫舍相似,不同的是每个元素可能有多个。

因为题目要求了如果选择num[i],就不能选择等于 nums[i] - 1nums[i] + 1 的元素,等价于198. 打家劫舍中我们不能选择连续的房间。

我们可以用map记录每个元素的个数,由题目给出的数字范围我们可以枚举1到10000的所有元素。用f[i]表示走到该点获取的最大点数,则:

f[i]=max(f[i-1],f[i-2]+i*cnt[i]);

3.代码

class Solution {
    
    
public:
    int deleteAndEarn(vector<int>& a) {
    
    
        map<int,int> cnt;
        for(auto x:a) cnt[x]++;
        vector<int> f(10001);
        f[1]=1*cnt[1];
        for(int i=2;i<10001;i++){
    
    
            f[i]=max(f[i-1],f[i-2]+i*cnt[i]);
        }
        return f[10000];
    }
};

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_45966440/article/details/122817695