Java_多状态动态规划_删除并获得点数

81 阅读2分钟

题目链接: leetcode.cn/problems/de…

题目描述:

给你一个整数数组 nums ,你可以对它进行一些操作。

每次操作中,选择任意一个 nums[i] ,删除它并获得 nums[i] 的点数。之后,你必须删除 所有 等于 nums[i] - 1 和 nums[i] + 1 的元素。

开始你拥有 0 个点数。返回你能通过这些操作获得的最大点数。

示例 1:

输入: nums = [3,4,2] 输出: 6 解释: 删除 4 获得 4 个点数,因此 3 也被删除。 之后,删除 2 获得 2 个点数。总共获得 6 个点数。

示例 2:

输入: nums = [2,2,3,3,3,4] 输出: 9 解释: 删除 3 获得 3 个点数,接着要删除两个 2 和 4 。 之后,再次删除 3 获得 3 个点数,再次删除 3 获得 3 个点数。 总共获得 9 个点数。

提示:

  • 1 <= nums.length <= 2 * 104
  • 1 <= nums[i] <= 104

题目解析

如果选择 nums[i]就要删除 nums[i] - 1、nums[i] + 1 ,着看着是不是很熟悉,如果我这样摆放 nums[i] - 1、nums[i]、nums[i] + 1,再换一种说法,如果选择 nums[i]就不能选择 nums[i - 1]、nums[i + 1]。其实这里的不能选择和删除是一样的道理,一定要删除吗?不选择一样是删除。想要把他转换成《打家劫舍Ⅱ》的套路。这就需要初始化一下题目给定的参数了。 题目中给了一个 nums 数组,我们需要再创建一个数组 arr[10001]用来统计 nums 中的所有点数。我们使用 arr[sums[i]]来统计 sums[i]的所有点数。比如说 sums[i] = 2,且数组中有 3 个 2。那么我们就将 arr[2] = 6;来统计 2 累计的所有点数,然后当选择 2 的时候,就不能选择 arr[1] 和 arr[3]。下面就和打家劫舍一样了。

代码

class Solution {
    public int deleteAndEarn(int[] nums) {
        int n = 10001;
        int[] arr = new int[n];
        for (int i : nums) {
            arr[i] += i;
        }
        int[] t = new int[n];
        int[] f = new int[n];
        t[0] = arr[0];
        for (int i = 1; i < n; i++) {
            t[i] = f[i - 1] + arr[i];
            f[i] = Math.max(f[i - 1], t[i - 1]);
        }
        return Math.max(t[n - 1], f[n - 1]);
    }
}