###### 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]); } }; ```