打家劫舍应用
作者:互联网
题目描述:
You are given an integer array nums. You want to maximize the number of points you get by performing the following operation any number of times:
Pick any nums[i] and delete it to earn nums[i] points. Afterwards, you must delete every element equal to nums[i] - 1 and every element equal to nums[i] + 1.
Return the maximum number of points you can earn by applying the above operation some number of times.
输入:
第一行一个整数n,表示数组长度;
第二行输入n个数mi,表示数组所有的元素。
输出:
一个整数,表示最大赚取到的points.
样例输入:
6
2 2 3 3 3 4
样例输出:
9
提示:
1<=n<=2*104(10的4次方)
1<=mi<=104(10的4次方)
这道题稍微处理一下,就变成了打家劫舍。
怎么处理?
对于原数组nums,我们提前处理出一个sum数组,这个sum数组表示什么呢?表示,以i为下标的在nums数组中所有i加起来的和。例如:
nums[] = 2 2 3 3 3 4
sum[] = 0 0 4 9 4
解释:nums中没有0,也没有1,所以在sum中以这两个数为下标的位置的值都为0.nums中有两个2,所以2这个下标处的值就是4,以此类推。
这有什么用呢?原题中,如果我们删掉一个数x,而其实在数组中这个x有很多个,我们自然可以把他们都删掉,以获取最大价值。而现在,拿着sum数组,你会发现,sum数组中的每一个值,我都可以选,也可以不选,一旦选了,那么,这个数的左右邻居都不能选了。比如说,在上面那个例子的数组中,第三个位置,下标为2,那如果我选了这个位置的值,4,那就意味着,他左边的0和右边的9,我都不能选了。正好对应原题中如果选x,那么x-1和x+1都不能选。这样确实很巧妙!
然后,就依葫芦画瓢了。
代码:
1 package com.hw.testdemo; 2 3 import java.util.Scanner; 4 5 public class Earn { 6 public int max(int a, int b) { 7 return a > b ? a : b; 8 } 9 10 public int rob(int[] nums) { 11 int pre = nums[0]; 12 int cur = max(nums[0], nums[1]); 13 int n = nums.length; 14 for (int i = 2; i < n; ++i) { 15 int next = max(pre + nums[i], cur); 16 pre = cur; 17 cur = next; 18 } 19 return max(pre, cur); 20 } 21 22 public int deleteAndEarn(int[] nums) { 23 int maxValue = 0; 24 for (int i : nums) { 25 maxValue = max(maxValue, i); 26 } 27 int[] sum = new int[maxValue+1]; 28 for (int i : nums) { 29 sum[i] += i; 30 } 31 return rob(sum); 32 } 33 public static void main(String[] args) { 34 Scanner s = new Scanner(System.in); 35 int n = s.nextInt(); 36 int[] nums = new int[n]; 37 for (int i = 0; i < n; ++i) { 38 nums[i] = s.nextInt(); 39 } 40 int ans = new Earn().deleteAndEarn(nums); 41 System.out.println(ans); 42 s.close(); 43 } 44 }
标签:应用,nums,int,sum,数组,打家劫舍,public,cur 来源: https://www.cnblogs.com/EvanTheGreat/p/15818992.html