个人主页:元清加油_【C++】,【C语言】,【数据结构与算法】-CSDN博客
个人专栏
力扣递归算法题
【C++】? ??
??????http://t.csdnimg.cn/6AbpV
数据结构与算法
前言:这个专栏主要讲述动态规划算法,所以下面题目主要也是这些算法做的 ?
我讲述题目会把讲解部分分为3个部分:
1、题目解析
2、算法原理思路讲解
3、代码实现
题目链接:删除并获得点数
题目
给你一个整数数组?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
我们这题使用动态规划,我们做这类题目可以分为以下五个步骤
这道题依旧是「打家劫舍I」问题的变型。 我们注意到题?描述,选择 x 数字的时候, x - 1 与 x + 1 是不能被选择的。像不像「打家 劫舍」问题中,选择 i 位置的?额之后,就不能选择 i - 1 位置以及 i + 1 位置的?额。因此,我们可以创建?个??为 10001 (根据题?的数据范围)的 hash 数组,将 nums 数 组中每?个元素 x ,累加到 hash 数组下标为 x 的位置处,然后在 hash 数组上来?次「打家劫舍」即可。
状态显示
dp1[i]表示:删除到?i 位置,不删?nums[i],此时最大的数。
dp2[i]表示:删除到 i 位置,不删?nums[i],此时最大的数。
状态转移方程
dp1[i] = dp2[i-1] + nums[i]
dp2[i] = max(dp1[i-1], dp2[i-1])
初始化(防止填表时不越界)
dp1[left] = nums[left];
填表顺序
根据「状态转移?程」得「从左往右,两个表?起填」。
返回值
max(dp1[N-1], dp2[N-1])
?
class Solution {
public:
int deleteAndEarn(vector<int>& nums)
{
const int N = 10001;
int arr[N] = { 0 };
for(auto x : nums)
{
arr[x] += x;
}
// 创建 dp 表
vector<int> f(N);
auto g = f;
// 填表
for(int i = 1; i < N; i++)
{
f[i] = g[i - 1] + arr[i];
g[i] = max(f[i - 1], g[i - 1]);
}
// 返回结果
return max(f[N - 1], g[N - 1]);
}
};