1. 题目来源
链接:740. 删除并获得点数
2. 题目解析
也是一个选不选的 dp
问题了,称其为 有限制的选择问题。 都可以拿 dp
来做,也是很经典的 dp
定义和状态转移。
思路:
- 哈希表维护每个数及其出现的次数。
- 状态定义:
f[i][2]
,f[i][0]
前i
个数中不选i
的最大价值,f[i][1]
前i
个数中选i
的最大价值。 - 答案:
max(f[N][0], f[N][1]);
- 初始化: 全部初始化为 0 即可。
- 状态转移:
- 如果第
i
个数被选,那么i-1
一定不能被选,f[i][1]
的最大值,应该等于f[i-1][0]
再加上选择的这个i
的收益。且应该将所有的i
全部选择完毕,因为如果选了一个i
那么,i-1
和i+1
都不能选了。f[i][1]=f[i-1][0]+i*cnt[i];
- 如果第
i
个数没被选,那么i-1
选不选都可以。即f[i][0]=max(f[i-1][0], f[i-1][1])
。
- 如果第
有限制的选择问题,如背包问题,lc198
的打家劫舍等,都很适用 dp
进行求解。
- 时间复杂度: O ( n ) O(n) O(n)
- 空间复杂度: O ( n ) O(n) O(n)
代码:
const int N = 1e4+5;
int cnt[N];
int f[N][2];
class Solution {
public:
int deleteAndEarn(vector<int>& nums) {
memset(cnt, 0, sizeof cnt);
memset(f, 0, sizeof f);
for (auto e : nums) cnt[e] ++ ;
int res = 0;
for (int i = 1; i < N; i ++ ) {
f[i][0] = max(f[i - 1][0], f[i - 1][1]);
f[i][1] = f[i - 1][0] + cnt[i] * i;
res = max(f[i][0], f[i][1]);
}
return res;
}
};