这题的思路和之前动态规划的打家劫舍问题Ⅱ比较类似。多了一步数组转换。
思路分析:
-
计算数组最大值: 首先,找到输入数组中的最大元素,以确定新数组的大小。
-
新数组初始化: 创建一个新的数组
newnums
,用于存储每个唯一元素的累积点数。数组大小为最大元素值加一,初始化所有元素为零。 -
累积点数: 遍历原始数组,将相同的元素值的点数累积到
newnums
数组中。 -
动态规划初始化: 创建一个动态规划数组
dp
,用于存储每个步骤的最大点数。初始化前两个元素,其中dp[0]
为零,dp[1]
为newnums[1]
。 -
动态规划递推: 从第三个元素开始,使用动态规划递推公式
dp[i] = max(dp[i - 1], dp[i - 2] + newnums[i])
,选择是否包含当前元素,以确保不相邻元素被选择。 -
返回结果: 返回动态规划数组中最后一个元素的值,即为最终的最大点数。
值得一提的是:例如2 2 3 3 3 4 这个,你会发现,虽然一次你只能取一个数,但是可以取多次,就比如,我第一次取3,两个2 和 4都删了,但是我还可以继续取两次3,2和4都删完了嘛,又没影响。所以我们把每个数(3)所占的点数(3×3=9)组成个新数组,用打家劫舍Ⅱ类似的思路解决。
class Solution {
public:
// 计算删除元素后的最大点数
int deleteAndEarn(vector<int>& nums) {
// 寻找输入数组中的最大元素
int numsmax = 0;
int i;
numsmax = *max_element(nums.begin(), nums.end());
// 创建一个新的数组,用于存储每个唯一元素的累积点数
vector<int> newnums(numsmax + 1, 0);
// 将相同元素值的点数累积到新数组中
for (i = 0; i < nums.size(); i++) {
newnums[nums[i]] += nums[i];
}
// 动态规划数组,存储每个步骤的最大点数
vector<int> dp(numsmax + 1, 0);
dp[0] = 0;
dp[1] = newnums[1];
// 动态规划递推
for (i = 2; i <= numsmax; i++) {
// 选择是否包含当前元素,确保不相邻元素被选择
dp[i] = max(dp[i - 1], dp[i - 2] + newnums[i]);
}
// 返回动态规划数组中最后一个元素的值,即为最终的最大点数
return dp[numsmax];
}
};