LWC 61:740. Delete and Earn
2017-12-04 18:24
351 查看
LWC 61:740. Delete and Earn
传送门:740. Delete and EarnProblem:
Given an array nums of integers, you can perform operations on the array.
In each operation, you pick any nums[i] and delete it to earn nums[i] points. After, you must delete every element equal to nums[i] - 1 or nums[i] + 1.
You start with 0 points. Return the maximum number of points you can earn by applying such operations.
Example 1:
Input: nums = [3, 4, 2]
Output: 6
Explanation:
Delete 4 to earn 4 points, consequently 3 is also deleted.
Then, delete 2 to earn 2 points. 6 total points are earned.
Example 2:
Input: nums = [2, 2, 3, 3, 3, 4]
Output: 9
Explanation:
Delete 3 to earn 3 points, deleting both 2’s and the 4.
Then, delete 3 again to earn 3 points, and 3 again to earn 3 points.
9 total points are earned.
Note:
The length of nums is at most 20000.
Each element nums[i] is an integer in the range [1, 10000].
思路:
最简单的思路,选择一个数后,比如[3, 4, 2]选择4,那么3失效,剩余数组为[2],当作子问题来求解即可,这是一种情况。选择3,那么4和2均失效,剩余数组为[],也可以当作子问题求解。选择2,则3失效,剩余数组为[4],在这几种情况中选择profit最多的情况即可。
但上述递归存在一个严重的问题,子问题无法被记录下来,因为选择是无序的。因此可以采用背包的思路,先对这些元素排序,这样数组变为[2, 3, 4],这样一来对于2选or不选,进一步影响3是否被包含,子问题能够轻而易举的被状态化,因为此时当前位置i,那么对应的i到n的位置可以表示子问题。而这些子问题与第一种求解思路不同的是,它们因位置而存在唯一性。
Java版本:(递归+记忆化)
public int deleteAndEarn(int[] nums) { Map<Integer, Integer> mem = new HashMap<>(); for (int n : nums) { mem.put(n, mem.getOrDefault(n, 0) + 1); } int[] cnt = new int[mem.size()]; Set<Integer> keys = mem.keySet(); int[] key = keys.stream().mapToInt(i -> i).toArray(); Arrays.sort(key); for (int i = 0; i < key.length; ++i) { cnt[i] = mem.get(key[i]); } dp = new int[20000 + 16]; return robot(key, cnt, 0); } int[] dp; public int robot(int[] key, int[] cnt, int pos) { if (pos >= key.length) return 0; if (dp[pos] > 0) return dp[pos]; int ans = 0; int choose = 0; // choose if (pos + 1 < key.length && key[pos + 1] - 1 == key[pos]) { choose = key[pos] * cnt[pos] + robot(key, cnt, pos + 2); } else { choose = key[pos] * cnt[pos] + robot(key, cnt, pos + 1); } ans = Math.max(ans, choose); // no choose ans = Math.max(ans, robot(key, cnt, pos + 1)); return dp[pos] = ans; }
递推版本:
public int deleteAndEarn(int[] nums) { if (nums.length == 0) return 0; Map<Integer, Integer> mem = new HashMap<>(); for (int n : nums) { mem.put(n, mem.getOrDefault(n, 0) + 1); } int[] cnt = new int[mem.size()]; Set<Integer> keys = mem.keySet(); int[] key = keys.stream().mapToInt(i -> i).toArray(); Arrays.sort(key); for (int i = 0; i < key.length; ++i) { cnt[i] = mem.get(key[i]); } int[] dp = new int[20000 + 16]; int last = key.length; dp[last - 1] = key[last - 1] * cnt[last - 1]; for (int i = last - 2; i >= 0; --i) { if (key[i] + 1 == key[i + 1]) { dp[i] = Math.max(dp[i], dp[i + 2] + key[i] * cnt[i]); } else { dp[i] = Math.max(dp[i], dp[i + 1] + key[i] * cnt[i]); } dp[i] = Math.max(dp[i], dp[i + 1]); } return dp[0]; }
简化map版本,用数组位置排序+计数:
public int deleteAndEarn(int[] nums) { int[] cnt = new int[10016]; for (int num : nums) cnt[num]++; int[] dp = new int[10016]; dp[0] = 0; dp[1] = cnt[1]; for (int i = 2; i <= 10000; ++i) { dp[i] = Math.max(dp[i - 1], dp[i - 2] + cnt[i] * i); } return dp[10000]; }
Python版本:
def deleteAndEarn(self, nums): """ :type nums: List[int] :rtype: int """ cnt = [0] * 10016 for num in nums: cnt[num] = cnt[num] + 1 dp = [0] * 10016 dp[0] = 0 dp[1] = cnt[1] for i in range(2, 10001): dp[i] = max(dp[i - 1], dp[i - 2] + i * cnt[i]) return dp[10000]
相关文章推荐
- Leetcode刷题:740. Delete and Earn
- 740[Medium]:Delete and Earn
- 740. Delete and Earn
- 740. Delete and Earn
- 740. Delete and Earn
- 740. Delete and Earn
- 740. Delete and Earn
- 【第十五周】740. Delete and Earn
- 740. Delete and Earn
- 740. Delete and Earn
- 740. Delete and Earn
- week17-leetcode #740-DeleteandEarn
- [LeetCode] Delete and Earn 删除与赚取
- Delete and Earn
- 算法练习(32):Delete and Earn
- 算法题目--Delete and Earn
- Leetcode 740. Delete and Earn
- Delete and Earn
- [LeetCode]740. Delete and Earn
- 740. Delete and Earn