标签:span out tco system public desc str 题解 div
给你一个整数数组 nums ,你可以对它进行一些操作。
每次操作中,选择任意一个 nums[i] ,删除它并获得 nums[i] 的点数。之后,你必须删除 所有 等于 nums[i] - 1 和 nums[i] + 1 的元素。
开始你拥有 0 个点数。返回你能通过这些操作获得的最大点数。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/delete-and-earn
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
输入:nums = [3,4,2]
输出:6
解释:
删除 4 获得 4 个点数,因此 3 也被删除。
之后,删除 2 获得 2 个点数。总共获得 6 个点数。
1 <= nums.length <= 2 * 104
1 <= nums[i] <= 104
此题仅比打家劫舍一样的原理多了一步操作,就是对同一数字可能又多个,这种只需要重新定义一个数组来存储即可,数组的下标为元数组的数据,值为总值,数组的size为元数组的最大值。
动态规划的守则:找到恒等式。
第i个数字是否取与第i-2和第i个数字有关,又由于相邻不能取,所以dp[i] = Math.max(dp[i - 1] , dp[i - 2] + nums[i]);
又因为所有操作仅与上两个数字有关,所以仅存储上两个数字即可。
public class DeleteAndEarnA {
public int deleteAndEarn(int[] nums) {
int len = nums.length, maxVal = 0;
for(int val : nums) {
maxVal = Math.max(maxVal, val);
}
int[] sum = new int[maxVal + 1];
for(int val : nums) {
sum[val] += val;
}
return rob(sum);
}
public int rob(int[] nums) {
/**
* @Method: rob
* @Author: haifwu
* @Version: 1.0
* @Date: 25/05/2021 21:11
* @param nums
* @Return: int
* @Description:
* 动态规划
* 是对第一种方式的优化
* 第一种方式需要另外定义一个数组来存储数据,
* 由于在操作过程中只用到了前两个数,所以我们只需要
* 保存前两个数即可。
*/
if (nums == null || nums.length == 0) {
return 0;
}
int len = nums.length;
if(len == 1) {
return nums[0];
}
if(len == 2) {
return Math.max(nums[0], nums[1]);
}
int first = nums[0], second = Math.max(nums[1], nums[0]);
for(int i = 2; i < nums.length; i++) {
int temp = Math.max(first + nums[i], second);
first = second;
second = temp;
}
return second;
}
public static void main(String[] args) {
int[] nums = {3, 4, 2};
System.out.println(new DeleteAndEarnA().deleteAndEarn(nums));
}
}
标签:span out tco system public desc str 题解 div
原文地址:https://www.cnblogs.com/haifwu/p/14810771.html