好家伙!!必须记录!!另类打家劫舍???就做小偷了就
好趴 看了题解 确实 必须记录! (哭辽_ 动态规划可太难了,感觉早上的打家劫舍已经踏入门口了,下午直接窗都看不见了)
废话太多了 记录开始:
先看题
- 题目:
给你一个整数数组 nums ,你可以对它进行一些操作。每次操作中,选择任意一个 nums[i] ,删除它并获得 nums[i] 的点数。之后,你必须删除 所有 等于 nums[i] - 1 和 nums[i] + 1 的元素。开始你拥有 0 个点数。返回你能通过这些操作获得的最大点数。 - 示例一:
输入:nums = [3,4,2]
输出:6
解释:
删除 4 获得 4 个点数,因此 3 也被删除。
之后,删除 2 获得 2 个点数。总共获得 6 个点数。
- 示例二:
输入:nums = [2,2,3,3,3,4]
输出:9
解释:
删除 3 获得 3 个点数,接着要删除两个 2 和 4 。
之后,再次删除 3 获得 3 个点数,再次删除 3 获得 3 个点数。
总共获得 9 个点数。
注意:
删除所有的nums[i] + 1 与 nums[i] - 1 而不是 nums[i + 1] or nums[i - 1]
先理一下思路:
如果 i 位置比 i - 1 位置刚好大 1 ,那么就是 i - 1 时刻的值与 i 时刻所有相等的值 + (i - 2)时刻所有的值之间的比较
另外,如果 i 位置比 i - 1 位置大大于1的值,那么就直接比较 i - 1 与 i 之间的值。
分析到这里也就是打家劫舍了——不能挨着,当然是有条件的,即二者差值是1的时候,有我没你,有你没我,看谁大了。
代码实现:
sort(nums.begin(), nums.end()); //先排序,方便判断
vector<int> m = {nums[0]};
for(int i = 1; i < n; i++)
{
int val = nums[i];
if(val == nums[i - 1]) //如果是一样的值直接相加
//相当于行个‘方便’,选择了这一家,其他跟这家门长的一样的,一块劫了就,反正不会‘报警’(慎言了这)
{
m.back() += val;
}
else if(val == nums[i - 1] + 1)
{
m.push_back(val);
}
else //上面所讲的第二种情况,那邻不邻居的无所谓了就,跟我没多大关系(摊手)
{
res += robb(m); //robb()打家劫舍代码
m = {val};
}
}
res += robb(m);
robb() 代码:
int robb(vector<int>& num)
{
if(num.size() == 1) return num[0];
if(num.size() == 2) return max(num[0], num[1]);
int l = num[0], r = max(num[0], num[1]);
for(int i = 2; i < num.size(); i++)
{
int tmp = r;
r = max(l + num[i], r);
l = tmp;
}
return r;
}
这个代码跟官方题解一样一样的,孩子太难了,自己在这里再理一遍思路,自己再过一遍
整个思路整理:
以223335为例:
将 nums[0] 也就是2放入容器m中;
循环开始:
val = nums[1] = 2
此时 num[i] == nums[i - 1], 二者相加;
直至 val = nums[2] = 3, 刚好 nums[i] - nums[i - 1] 的值为1,将3放入容器中,继续循环重复相加;
直至val = nums[5] = 5, 跟前一位 nums[i - 1] 相差大于1,那么之前的情况跟我没啥关系了,我不是你们邻居了,你们前两个不能相邻反正,看你们谁富裕了,进入相应的打家劫舍代码;
最后全部相加就可以啦~
就这样吧先,又是嫌弃自己辣鸡的一天…