动态规划-LCR 090.打家劫舍II-力扣(LeetCode)
一、题目解析
本题与打家劫舍的最大区别在于房子不是线性分布的了,而是首尾相连的环形分布,即如果偷了第一间房子,那么最后一间房子就不能偷了,因为它们是相连的。
二、算法原理
在分析之前我们可以先讨论上面提到的第一间房子偷or不偷的不同状态
我们需要求两者中的最大值,所以max(nums[0]+rob1(nums,2,n-2),rob1(nums,1,n-1))
这里将问题转化,可以选择回顾打家劫舍,也可以继续往下看,因为都是差不多的。
链接:动态规划-LCR 089.打家劫舍-力扣(LeetCode)-CSDN博客
1.状态表示
对于到达i位置时,此时金额最大,并且存在该位置是否偷窃的问题,所以f[i]表示:到达i位置时,偷房间时,此时的最大金额;g[i]表示:到达i位置时,不偷房间,此时的最大金额
2.状态转移方程
省流:f[i]=g[i-1]+nums[i]
g[i]=max(f[i-1],g[i-1])
3.初始化
f[0]=nums[0],g[0]=0,rob1函数初始化为f[left]=nums[left],g[left]=0,这里的rob1函数就是打家劫舍里的函数修改符合区间操作的。
4.填表顺序
从左往右,两个表一起填
5.返回值
打家劫舍返回值为max(f[n-1],g[n-1])(n为nums的大小),打家劫舍II的返回值为max(nums[0]+rob1(nums,2,n-2),rob1(nums,1,n-1))
这里我们的分析是有点错误的对于区间的处理划分,假如数据小于等于3呢?这里是一个小坑
根据上面的思路,自己动手实现,链接:LCR 090. 打家劫舍 II - 力扣(LeetCode)
三、代码示例
class Solution {
public:int rob1(vector<int>& nums,int left,int right) {int n = nums.size();vector<int> f(n),g(n,0);f[left] = nums[left];for(int i = left;i<=right;i++){f[i] = g[i-1]+nums[i];g[i] = max(f[i-1],g[i-1]);}return max(f[right],g[right]);}int rob(vector<int>& nums) {int n = nums.size();if(n == 1) return nums[0];if(n == 2) return max(nums[0],nums[1]);if(n == 3) return max(nums[0],nums[1]);return max(nums[0]+rob1(nums,2,n-2),rob1(nums,1,n-1));}
};
我们之前的分析是建立在nums的大小大于4的基础上的,但给出小于等于3的nums时我们分析的逻辑就排不上用场了,所以需要单独这三种情况
看到最后,如果对您有所帮助,还请点赞、收藏、关注一波,点点关注不迷路,我们下期再见!