---
# System prepended metadata

title: 740. Delete and Earn
tags: [Leetcode, medium, python, array, c++, dynamic programming]

---

###### tags: `Leetcode` `medium` `dynamic programming` `array` `python` `c++`

# 740. Delete and Earn

## [題目連結:] https://leetcode.com/problems/delete-and-earn/description/

## 題目:
You are given an integer array ```nums```. You want to maximize the number of points you get by performing the following operation any number of times:

* Pick any ```nums[i]``` and delete it to earn ```nums[i]``` points. Afterwards, you must delete **every** element equal to ```nums[i] - 1``` and **every** element equal to ```nums[i] + 1```.

Return the **maximum number of points** you can earn by applying the above operation some number of times.

**Example 1:**
```
Input: nums = [3,4,2]
Output: 6
Explanation: You can perform the following operations:
- Delete 4 to earn 4 points. Consequently, 3 is also deleted. nums = [2].
- Delete 2 to earn 2 points. nums = [].
You earn a total of 6 points.
```
**Example 2:**
```
Input: nums = [2,2,3,3,3,4]
Output: 9
Explanation: You can perform the following operations:
- Delete a 3 to earn 3 points. All 2's and 4's are also deleted. nums = [3,3].
- Delete a 3 again to earn 3 points. nums = [3].
- Delete a 3 once more to earn 3 points. nums = [].
You earn a total of 9 points.
```

## 解題想法:
* 此題為給一數組，每次選擇任一nums[i]，刪除並獲得nums[i]的點數，且必須刪除每個等於nums[i]+1或nums[i]-1的數
    * 求能獲得的最大總數
* 起始動作:
    * 題目規定: 1 <= nums[i] <= 104
    * 數字對多到10000，先記錄所有數出現的總和
    ``` python=
    sum=[0]*10001
    for i in nums: #先填入各數字加總
        sum[i]+=i
    ```
    
* **Sol1**使用DP:
    * 定義兩組dp
        * token=[0] * 10001  :**拿該數**
            * init: token[0]=sum[0]
        * skip=[0] * 10001  :**不拿該數**
    * 轉移方程式:
        * 取: max(上個數有取vs上個數沒取+取當前數字)
        ``` python=
        token[i]=max(token[i-1],skip[i-1]+sum[i])
        ```
        * 不取: max(上個數不取vs上個數有取) 
        ``` python=
        skip[i]=max(skip[i-1],token[i-1])
        ```
    * return max(token[-1], skip[-1])

* **Sol2**: 
    * 視為house robber不能搶鄰居 [198. House Robber](/YIzmiuAqRfm6voICu36IXg)


## Python:
``` python=
class Solution(object):
    def deleteAndEarn(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        #法1
        sum=[0]*10001
        for i in nums:
            sum[i]+=i
        token=[0]*10001 #拿該數
        skip=[0]*10001 #不拿該數
        token[0]=sum[0]
        for i in range(1,10001):
            #取: max(上個數有取vs上個數沒取+當前數字)
            token[i]=max(token[i-1],skip[i-1]+sum[i])
            #不取: max(上個數不取vs上個數有取)
            skip[i]=max(skip[i-1],token[i-1])
        return max(token[-1],skip[-1])

        #法2
        #數字最多到10000
        sum=[0]*(10001)
        #先填入各數字加總
        for i in nums:
            sum[i]+=i
        #因為i從 2 3 4.... 可以看成house robber不能搶鄰居
        for i in range(2,10001):
            sum[i]=max(sum[i-1],sum[i-2]+sum[i])
        return sum[-1]

ressult=Solution()
ans=ressult.deleteAndEarn(nums = [2,2,3,3,3,4])
print(ans)
```

## C++:
``` cpp=
#include<bits/stdc++.h>
using namespace std;

class Solution {
public:
    int deleteAndEarn(vector<int>& nums) {
        vector<int> sum(10001, 0), token(10001, 0), skip(10001, 0);
        for (int val: nums) sum[val]+=val;
        token[0]=sum[0];
        for (int i=1; i<10001; i++){
            token[i]=max(token[i-1], skip[i-1]+sum[i]);
            skip[i]=max(skip[i-1], token[i-1]);
        }
        return max(token[10000], skip[10000]);
    }
};
```