leetcode 动态规划之 删除并获得点数
哈喽哈喽,我是你们的金樽清酒,今天啊,我要向大家介绍一题难一点的动态规划问题——删除并获得点数。并且这是属于斐波那契型的。给你们看看我刷的斐波那契型的动态规划问题,几道题刷下去,这类问题也就轻而易举了。
先看题
给你一个整数数组 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 * 1041 <= nums[i] <= 104
题目分析
这道题要删除一个数,得到它得点数,连带把相邻的数也删除。注意仔细分析题目哦,例如上面有三个三,三个三是都要删除并获得点数的。而且只有相邻的数字要删除,如删除3后,是数字2和数字4要被删除且不或的点数。诶,是不是拿到这题有点摸不着头脑,这也不像我们一般的动态规划呀,不知道为什么,总感觉大脑很乱。
解题思路----转化为打家劫舍问题
首先我们简单的回顾一下打家劫舍问题。一个小偷打劫一个村子,每个房子都放有不同价值的财宝,但是小偷不能同时偷相邻的房子,会触发警报,诶,然后就用动态规划解决问题。没做过的小伙伴可以先去做一下那一题哦,这一题是打家劫舍的进阶版。那我们怎么把这个问题转化为打家劫舍问题呢?那就是创建一个新数组,以nums的值为下标,将一样的数加起来,那就是打家劫舍的问题啦,新数组的值不就是财富数嘛,而且以数组值为下标,解决了相邻数删除的问题,跟打家劫舍就异曲同工啦。
或许你还是一头雾水,那我给你举个例子nums = [2,2,3,3,3,4] arr=[0,0,4,9,6]
nums=2 新数组下标为2,值为几个nums=2相加,下标0和1在nums里面没有值,所以下标0和1的值是为空的,给它们的值赋上0,那这样就可以变为打家劫舍的问题啦。
题解代码
/**
* @param {number[]} nums
* @return {number}
*/
var deleteAndEarn = function(nums) {
if (nums.length <= 0) return 0
let nlen = nums.length
let arr = []//生成一个数组,数组元素作为下表,值为相同元素相加
for (let i = 0; i < nlen; i++) {
let value = nums[i]
if(arr[value])
{
arr[value] +=value
}else
{
arr[value]=value//这一步是给它赋初值
}
}
for(let i=0;i<arr.length;i++)
{
arr[i]=arr[i]||0
}//给empty元素填充为0
const dp= new Array(arr.length+1)
//开始打家劫舍问题
dp[0]=0
dp[1]=arr[0]
for(var i=2;i<=arr.length;i++)
{
dp[i]=Math.max(dp[i-1],dp[i-2]+arr[i-1])
}
return dp[arr.length]
};