740[Medium]:Delete and Earn

Part1:题目描述

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].

  • Part2:解题思路
  •   动态规划的题目能够想出动态规划的方程真的是很关键的第一步,可是很难过我现在还没能成功自己找出过动态规划方程,但是我会不断积累经验的!这道题目我是看了leetcode上的soluton上的解题思路做的,现在再用我自己的语言总结一下,当作巩固吧。

      对于每一个nums[i],都有选和不选2种可能,当前的选择结果值也会以同样的方式影响下一步,这也正是能用动态规划的地方,可以化成一小步一小步的解决。

      所以我们需要记录会对下一步造成影响的当前的所有值:

      previous:当前这一步选择的值。nums[i+1]与之是否相邻,会影响选择nums[i+1]之后used和avoid值的结果。相邻选择nums[i+1],used = avoid+nums[i+1];不相邻选择nums[i+1],used = max(avoid, used)(这里的avoid, used的值是上一步中的)+nums[i+1];

      used:选择当前nums[i]之后的总point

      avoid:不选择当前nums[i]之后的总point

      最终我们要求的也应该是max(avoid, used),因为到vector里的最后一个元素时,我们也不能保证选他和不选他谁的值最大,所以我们要取二者的最大值。

    补充说明:

    虽然题目描述中说,选了nums[i]之后nums[i-1]和nums[i+1]都不能选择,但是我们排序之后限制选了nums[i]之后nums[i + 1]就不能选结果也是一样的。


  • Part3:代码

    #include<iostream>
    #include<vector>
    #include<algorithm>
    
    using namespace std;
    
    int deleteAndEarn(vector<int>& nums) {
    	int length = nums.size();
    	int used = 0, avoid = 0, previous = 0;
    	if (length == 0) return 0;
    	sort(nums.begin(), nums.end());
    	
    	for (int i = 0; i < length; i++) {
    		int temp = max(used, avoid);
    		if ((i != 0) && (nums[i - 1] == nums[i])) {
    			used += nums[i];
    		}
    		else if (previous + 1 == nums[i]) {
    			used = avoid + nums[i];
    			avoid = temp;
    		} else {
    			used = temp + nums[i];
    			avoid = temp;
    		}
    		previous = nums[i];
    	}
    	
    	return max(used, avoid); 
    }
    
    int main() {
    	int num;
    	cin >> num;
    	vector<int>nums;
    	for (int i = 0; i < num; i++) {
    		int temp;
    		cin >> temp;
    		nums.push_back(temp); 
    	}
    	cout << deleteAndEarn(nums) << endl;
    	return 0;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值