LeetCode740. 删除并获得点数
Posted Zephyr丶J
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode740. 删除并获得点数相关的知识,希望对你有一定的参考价值。
LeetCode740. 删除并获得点数
2021.5.5每日一题,动态规划,我的思路如下
class Solution {
public int deleteAndEarn(int[] nums) {
//看到题想到了动态规划,但是怎么规又是个问题,先排序应该没问题
//dp[i]定义为到当前为止,删除数获得的最大点数
//先举例想想,如果2是第一个数,删除一个2,到目前为止的点数为dp[2] = 2的数量×2
//然后删除3,dp[3] = 3 的数量×3 + dp[1],不删除3,那么就是dp[2]
//dp[4] = 4 的数量×4 + dp[2]
//想到这里,突然想到一个问题,那数不是连续的该怎么办呢,如果是一个单独的数,删了就是最大了
//所以先找出数组中最大的数,然后挨个删,删除每个数字的值用一个数组记录下来,然后直接计算就行
//没有的数就是0,这样也不用排序了
int l = nums.length;
int maxNum = 0;
for(int num : nums){
maxNum = Math.max(maxNum, num);
}
//0 到 最大值
int[] sum_num = new int[maxNum + 1];
//例如,要删除3,获得的点数就是3的数量乘以3
for(int num : nums){
sum_num[num] += num;
}
//从0到maxNum删除
int[] dp = new int[maxNum + 1];
//初始化
dp[0] = 0;
dp[1] = sum_num[1];
for(int i = 2; i <= maxNum; i++){
dp[i] = Math.max(dp[i - 1], dp[i - 2] + sum_num[i]);
}
return dp[maxNum];
}
}
看了答案,官解中还有把整个数组分成一个个小的连续的数组,然后再套用打家劫舍的方法,然后按着这个分组的思路,又写了一个代码,有点繁琐,不过思路没问题
class Solution {
public int deleteAndEarn(int[] nums) {
//看了答案,或者这样,就是相当于分成一个个连续子数组吧,先排序,当下一个数和当前数相差1的时候,就和打家劫舍一样转移
//不连续的时候,那就直接删了
Arrays.sort(nums);
int l = nums.length;
//统计每个数字的个数
Map<Integer, Integer> map = new HashMap<>();
for(int num : nums){
map.put(num, map.getOrDefault(num, 0) + 1);
}
//前面补个0,防止边界的判断
int[] dp = new int[map.size() + 1];
int index = 2;
dp[0] = 0;
dp[1] = nums[0] * map.get(nums[0]);
for(int i = 1; i < l; i++){
//如果两个数相同,跳过
if(nums[i] == nums[i - 1])
continue;
else if(nums[i] - 1 == nums[i - 1]){
dp[index] = Math.max(dp[index - 1], dp[index - 2] + nums[i] * map.get(nums[i]));
index++;
}
else{
dp[index] = dp[index - 1] + nums[i] * map.get(nums[i]);
index++;
}
}
return dp[--index];
}
}
以上是关于LeetCode740. 删除并获得点数的主要内容,如果未能解决你的问题,请参考以下文章
leetcode740. 删除并获得点数(线性相邻dp问题)