删除并获得点数 leetcode740 java

题目描述

给你一个整数数组 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 * 10^4
1 <= nums[i] <= 10^4

思路

  1. “选择任意一个 nums[i] ,删除它并获得 nums[i] 的点数。之后,你必须删除 所有 等于 nums[i] - 1 和 nums[i] + 1 的元素”。由此可知,数值连续时,相邻的数值是无效的。
  2. “通过这些操作获得的最大点数”,也即去除相邻数值,nums数组中能选择到的最大值。
  3. 通过以上分析,本题与打家劫舍Ⅰ的思想相似,区别在于,打家劫舍数组是以索引为顺序判断连续与否,本题是以数组中数值的大小为顺序(+1或-1)判断连续与否;且本题会出现多个相同数值。
  4. 那么,我们需要将数组判断连续的方式进行处理、相同数值合并即可解决该题。此处处理的方法为,将数组中的值映射到新数组索引上,索引对应的值为该数值在nums数组中的(数值*出现次数)。

代码

public class Num740_deleteAndEarn {
    public int deleteAndEarn(int[] nums) {
        int n = 10001;
        int[] arr = new int[n];
        for(int num : nums){   //预处理,将nums的点数值映射到下标
            arr[num] += num;
        }

        int[] f = new int[n];  //选择i索引
        int[] g = new int[n];  //不选择i索引

        f[0] = arr[0];  //初始化

        for(int i = 1;i < n;i ++){   //填表
            f[i] = g[i - 1] + arr[i];
            g[i] = Math.max(f[i - 1],g[i - 1]);
        }

        return Math.max(f[n - 1],g[n - 1]);
    }
}

你可能感兴趣的:(刷题,java,算法,leetcode)