这是我参与8月更文挑战的第17天,活动详情查看:8月更文挑战
740. 删除并获得点数
给你一个整数数组 nums ,你可以对它进行一些操作。
每次操作中,选择任意一个 nums[i] ,删除它并获得 nums[i] 的点数。之后,你必须删除每个等于 nums[i] - 1 或 nums[i] + 1 的元素。
开始你拥有 0 个点数。返回你能通过这些操作获得的最大点数。
示例 1:
输入:nums = [3,4,2] 输出:6 解释: 删除 4 获得 4 个点数,因此 3 也被删除。 之后,删除 2 获得 2 个点数。总共获得 6 个点数。
解题思路
根据题意,在选择了元素 x 后,该元素以及所有等于 x-1 或 x+1 的元素会从数组中删去。
因此我们将代码分为两个部分
- 统计每个元素出现的次数(方便计算删除元素后的得分),并且找出最大值(为了缩小dp数组的长度)
for _, num := range nums {
cnt[num]++
if num>max{
max=num
}
}
- 状态转移 dp[i][0]代表当前元素是i,并且不删除该元素。因此前一个元素可以是被删除元素,也可以不是 dp[i][1]代表当前元素是i,需要删除该元素。因此前一个元素必须不为删除元素(因为如果前一个元素是删除元素,该元素已经被删除掉了),并且加上删除后的得分
for i := 1; i <= max; i++ {
dp[i][0]=MaxV(dp[i-1][0],dp[i-1][1])
dp[i][1]=dp[i-1][0]+i*cnt[i]
}
代码
func MaxV (a int,b int) int {
if a>b{
return a
}else {
return b
}
}
func deleteAndEarn(nums []int) int {
cnt:=make([]int,10008)
max:=-1
for _, num := range nums {
cnt[num]++
if num>max{
max=num
}
}
dp:=make([][2] int,max+1)
for i := 1; i <= max; i++ {
dp[i][0]=MaxV(dp[i-1][0],dp[i-1][1])
dp[i][1]=dp[i-1][0]+i*cnt[i]
}
return MaxV(dp[max][0],dp[max][1])
}
时间复杂度:O(N+M),其中 NN 是数组nums 的长度,M 是nums 中元素的最大值。
空间复杂度:O(M)。