leetcode198. 打家劫舍(java-动态规划)

打家劫舍

  • leetcode198. 打家劫舍
    • 题目描述
  • 暴力递归
    • 解题思路
    • 代码演示
  • 递归 + 缓存
    • 解题思路
    • 代码演示
  • 动态规划
    • 解题思路
    • 代码演示
  • 动态规划专题

leetcode198. 打家劫舍

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/house-robber

题目描述

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。

示例 1:
输入:[1,2,3,1]
输出:4
解释:偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。
偷窃到的最高金额 = 1 + 3 = 4 。

示例 2:
输入:[2,7,9,3,1]
输出:12
解释:偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。
偷窃到的最高金额 = 2 + 9 + 1 = 12 。

提示:
1 <= nums.length <= 100
0 <= nums[i] <= 400

暴力递归

解题思路

递归解法时,每到一个房间 有两个选择。偷或者不偷
偷的情况:
那么下一间就不能偷了,要去下下一间去偷。
不偷的情况:
可以去下一间继续做选择。
递归过程就有了。
最后选择比较出一个最大值进行返回。

代码演示

/**
* 主方法。
*/
  public int rob(int[] nums) {
   	
     return process(nums,0); 
 }

	/**
	* 递归
	* index 下标值,来到了哪个房间
	*/
    public int process(int[]nums,int index){
    	//base case  越界时 返回0
        if(index >= nums.length){
            return 0;
        }
        //选择不打劫的情况,去下一房间继续做选择
        int p1 = process(nums,index + 1);
        //选择打劫的情况,下一间就不能偷了,去下下一间做选择,
        int p2 = process(nums,index + 2);
        //选择偷时,这个房间的值加上后序的选择,
        p2 += nums[index];
        //返回最大值。
        return Math.max(p1,p2);

    }

递归 + 缓存

解题思路

在递归的过程中,找到重复的值,也就是变量,进行缓存,
这里的变量就是下标值,index.所以用一个数组就可以进行缓存了。

代码演示

  /**
  * 主方法调用
  */
  public int rob(int[] nums) {
  		//缓存,初始化为 -1.
       int[]ans =  new int[nums.length + 1];
       Arrays.fill(ans,-1);
       return process(nums,0,ans); 
        
    }



/**
* 递归加缓存
* index 下标值 来到的房间
* ans 缓存
*/
  public int process(int[]nums,int index,int[]ans){
  	//base case 
        if(index >= nums.length){
            return 0;
        }
        //有缓存时  直接从缓存中拿
        if(ans[index] != -1){
            return ans[index];
        }
        //选择不打劫
        int p1 = process(nums,index + 1,ans);
        int p2 = process(nums,index + 2,ans);
        p2 += nums[index];
       //把结果放进缓存中
        ans[index] =  Math.max(p1,p2);
        return ans[index];

    }

动态规划

解题思路

动态规划是对递归加缓存的改写,我们把递归过程改写成从动态规划表中去拿。
三个步骤:
1.根据 base case 初始化动态规划表
2.把递归过程改写成从缓存表中拿,
3.返回递归调用的初始状态。

代码演示

/**
* 主方法调用
*/
  public int rob(int[] nums) {
  
    return dp(nums);     
    }
/**
* 动态规划表
*/
 public int dp(int[] nums){
        int N = nums.length;
        //dp 表
        int[]dp = new int[N + 1];
        //base case 进行初始化
        dp[N] = 0;
        //从N - 1 进行赋值
        for(int i = N - 1;i >= 0;i--){
           int p1 = dp[i+1];
           //判断越界 
           int p2 = i + 2 > N ? nums[i] : nums[i] + dp[i + 2]; 
           dp[i] = Math.max(p1,p2);
        }
        return dp[0];
    }

动态规划专题

leetcode174. 地下城游戏

打败怪兽的概率

leetcode688. 骑士在棋盘上的概率

凑零钱.钱币的组合有多少种

最小路径和

leetcode.486. 预测赢家

leetcode51. N 皇后

背包问题–填满背包的最大价格

你可能感兴趣的:(数据结构,算法,java,java,动态规划,leetcode,算法,数据结构)