手撕算法——打家劫舍

打家劫舍

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];
    }
}

你可能感兴趣的:(手撕算法)