代码随想录动态规划——打家劫舍

题目

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。

给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。

示例 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 。

提示:

0 <= nums.length <= 100 0 <= nums[i] <= 400

思路

动规五部曲:

  1. 确定dp数组
    dp[i]:考虑下标i(包括i)以内的房屋,最多可以偷窃的金额为dp[i]
  2. 确定递推公式
    决定dp[i]的因素就是偷不偷第 i 个房间;
    如果偷的话,那么dp[i] = dp[i-2] + nums[i],因为如果偷第i个房间,那么第i-1房间一定是不考虑的,相当于是在前i-2间房里偷到的最大金额dp[i-2]加上第i间房偷到的金额nums[i]
    如果不偷的话,dp[i] = dp[i - 1],即考虑第i-1间房(只是考虑并不是一定要偷)
    然后dp[i]取最大值,即dp[i] = max(dp[i - 2] + nums[i], dp[i - 1])
  3. 初始化
    递推公式的基础就是dp[0]dp[1],从dp[i]的定义上来讲,dp[0] 一定是 nums[0]dp[1]就是nums[0]nums[1]的最大值即:dp[1] = max(nums[0], nums[1])
  4. 确定遍历顺序
    dp[i] 是根据dp[i - 2]dp[i - 1] 推导出来的,那么一定是从前到后遍历
  5. 举例推导
    以示例二,输入[2,7,9,3,1]为例:
    在这里插入图片描述
    java代码如下:
class Solution {
	public int rob(int[] nums){
		int n = nums.length;
		if(nums == null || n == 0){
			return 0;
		}
		if(n == 1){
			return nums[0];
		}
		
		int[] dp = new int[n];//因为从递推同时可以看到,qi求dp[i]只需要计算到i-1即可,所以只需要到 n-1,并且要从0开始计算,所以0~n-1一共n个元素
		dp[0] = nums[0];
		dp[1] = Math.max(nums[0],nums[1]);
		for(int  i = 2; i < n; i++){
			dp[i] = Math.max(dp[i-1], dp[i-2] + nums[i]);
		}
		return dp[n - 1];//因为开创dp数组一共就n个数,所以最后的是n-1
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HDU-五七小卡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值