打家劫舍
198. 打家劫舍
打家劫舍问题是一个经典的动态规划问题,但是当我做中兴的笔试题的时候,竟然输在没有读懂题目上,归根节点,还是对该类问题的不熟悉。同时,自己的阅读能力也有待提升
直接上代码
class Solution {
public int rob(int[] nums) {
if(null==nums||nums.length<=0){
return 0;
}
if(nums.length==0){
return nums[0];
}
/*
动态规划
dp[i] 区间[0,i]能偷到的最高金额
关系表达式
不偷第i家 dp[i]=dp[i-1]
投第i家 dp[i]=dp[i-2]+nums[i];
dp[i]=Math.max(dp[i-1])
*/
int len=nums.length;
int dp[]=new int[len+1];
dp[0]=0;
dp[1]=nums[0];
for(int i=2;i<=len;i++){
dp[i]=Math.max(dp[i-1],dp[i-2]+nums[i-1]);
}
return dp[len];
}
}
题目变形—汉姆贝克
package zte;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
/**
贝壳汉姆想在弟弟生日那天给他送巧克力作为礼物,他让他的弟弟在篮子里挑选一些上面印有数字的标牌。每当选择一个带有数字X的标牌时,贝克汉姆给他弟弟的巧克力数等于数字X与篮中的编号为X的标牌总数相乘等到的乘积。他从篮中取出了所有X编号的标牌,以及编号刚好大于和小于X的,另外两个数字的标牌。然后,他让他的弟弟选择另一个标牌,并重复此过程,直到所有标牌都被移除。
写一个算法,帮助贝克汉姆的弟弟获得最多的巧克力作为礼物。
输入
该函数/方法的输入包括两个参数
numsOfTokens 一个整数,表示标牌数目。
printOnToken 一个整数,表示印在各标牌上的数字。
输出
返回一个整数,表示最大的巧克力数
示例
输入:
numOfTokens=9
printOnToken={2,3,3,4,5,4,4,6,8}
输出:
22
解释:
第一步:列表={2,3,3,4,5,4,4,6,8}。选择8,删除所有的8和6.
第二步:列表={2,3,3,4,5,4,4,6,8}。选择4,删除列表中的3和4.
第三步:列表={2}选择2,删除列表中的2。
第四步:最大巧克力数为 8*1+4*3+2*1=22
*/
public class Test02 {
public static void main(String[] args){
int input[]={2,3,3,4,5,4,4,6,8};
int case1[]={5,8,1,37,2,17};
int case2[]={3,4,4,3,4,5,4,4,5};
Solution solution=new Solution();
System.out.println( solution.getMaxChoc(input));
System.out.println( solution.getMaxChoc(case1));
System.out.println( solution.getMaxChoc(case2));
}
}
class Solution{
public int getMaxChoc(int[] nums){
int res=0;
//将数组元素存入map中 使用TreeMap的话可以自动进行排序
Map<Integer,Integer> map =new TreeMap<>();
for(int i:nums){
if(map.containsKey(i)){
map.put(i,map.get(i)+1);
}else{
map.put(i,1);
}
}
int len=map.size();
int tmp[]=new int[len];
int index=0;
for(Map.Entry<Integer,Integer> e:map.entrySet()){
tmp[index++]=e.getKey()*e.getValue();
}
/*
* 使用动态规划 类比小偷问题
* dp[i] 表示到 区间[0,i]最大的数
* */
int dp[]=new int[len+1];
dp[0]=0;
dp[1]=tmp[0];
for(int i=2;i<=len;i++){
dp[i]=Math.max(dp[i-1],dp[i-2]+tmp[i-1]);
}
return dp[len];
}
}