题目
给你一个整数数组 nums ,你可以对它进行一些操作。每次操作中,选择任意一个 nums[i] ,删除它并获得 nums[i] 的点数。之后,你必须删除 所有 等于 nums[i] - 1 和 nums[i] + 1 的元素。开始你拥有 0 个点数。返回你能通过这些操作获得的最大点数。示例 1:输入:nums = [3,4,2]
输出:6
解释:
删除 4 获得 4 个点数,因此 3 也被删除。
之后,删除 2 获得 2 个点数。总共获得 6 个点数。
示例 2:输入:nums = [2,2,3,3,3,4]
输出:9
解释:
删除 3 获得 3 个点数,接着要删除两个 2 和 4 。
之后,再次删除 3 获得 3 个点数,再次删除 3 获得 3 个点数。
总共获得 9 个点数。提示:1 <= nums.length <= 2 * 104
1 <= nums[i] <= 104
方法 动态规划
分析
- 当我选择一个x之后,x-1和x+1被删除(不计入积分),与打家劫舍类似,如果我取了一个,旁边的两个就不能在取了.
- num[i] 的值可以重复,即值x可以对应多个i值.
我们通过遍历,寻找nums中的最大值,以此来框定动态规划的大小.(我们将打家劫舍部分做修改,用作函数rob,函数参数numssize以此方法被计算)
1.初始状态
将x值合并,当我们取x时,将所有x取到.
求出maxnum框定rob传参大小.
2.转移处理
使用rob函数进行处理
3.结束状态
通过rob函数求出max并返回.
代码
int rob(int* nums, int numsSize) {if(numsSize == 1) return nums[0];int first = nums[0], second = fmax(nums[0], nums[1]);for (int i = 2; i < numsSize; i++) {int temp = second;second = fmax(first + nums[i], second); first = temp;}return second;
}int deleteAndEarn(int* nums, int numsSize) {int maxnum = 0;for (int i = 0; i < numsSize; i++) {maxnum = fmax(maxnum, nums[i]);} //找到最大值int sum[maxnum + 1] = {}; //框定范围for (int i = 0; i < numsSize; i++) {sum[nums[i]] += nums[i]; //计算所有为nums[i]的值的总和}return rob(sum,maxnum+1);
}
题目链接:https://leetcode.cn/problems/delete-and-earn/?envType=study-plan-v2&envId=dynamic-programming