leetcode 740. Delete and Earn | 740. 删除并获得点数(暴力递归->傻缓存->DP)

x33g5p2x  于2021-11-17 转载在 其他  
字(1.2k)|赞(0)|评价(0)|浏览(315)

题目

https://leetcode.com/problems/delete-and-earn/

题解

建立 help 数组,相当于一个(正向)索引表。

先排序,因为删除的顺序不影响最优结果(实际上是影响结果的,只不过最优解一定是从小到大删除的,因为如果先删除中间的元素的话,它的两边可能被误伤,而如果从边缘开始删除的话,只能误伤到一侧。)

  1. class Solution {
  2. public int deleteAndEarn(int[] nums) {
  3. Map<Integer, Integer> map = new HashMap<>();
  4. for (int n : nums) {
  5. int count = map.getOrDefault(n, 0);
  6. map.put(n, count + 1);
  7. }
  8. int[][] help = new int[map.keySet().size()][2];
  9. int p = 0;
  10. for (int k : map.keySet()) {
  11. help[p][0] = k;
  12. help[p++][1] = map.get(k);
  13. }
  14. // 删除顺序不影响结果(至少从小到大删除结果不会更差),所以先排序
  15. Arrays.sort(help, Comparator.comparingInt(o -> o[0]));
  16. // Approach 2: Recursion with Memoization
  17. // return process(help, 0, dp);
  18. // Approach 3: Dynamic Programming
  19. int[] dp = new int[help.length + 2];
  20. Arrays.fill(dp, -1);
  21. dp[help.length] = 0;
  22. dp[help.length + 1] = 0;
  23. for (int i = help.length - 1; i >= 0; i--) {
  24. int step = (i + 1 < help.length && help[i][0] + 1 == help[i + 1][0]) ? 2 : 1;
  25. dp[i] = Math.max(dp[i + 1], dp[i + step] + help[i][0] * help[i][1]);
  26. }
  27. return dp[0];
  28. }
  29. // 在当前i位置,删或不删,能够获得的最大收益
  30. // public int process(int[][] help, int i, int[] dp) {
  31. // if (i >= help.length) return 0;
  32. // if (dp[i] >= 0) return dp[i];
  33. //
  34. // int step = (i + 1 < help.length && help[i][0] + 1 == help[i + 1][0]) ? 2 : 1;
  35. // int p1 = process(help, i + 1, dp); // 不删i位置
  36. // int p2 = process(help, i + step, dp) + help[i][0] * help[i][1]; // 删i位置
  37. //
  38. // dp[i] = Math.max(p1, p2);
  39. // return dp[i];
  40. // }
  41. }

相关文章