本次学习目标为 力扣初级算法-动态规划,其中主要的LC如下:
- 打家劫舍 -----([链接](https://leetcode-cn.com/leetbook/read/top-interview-questions-easy/xnq4km/)
你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。示例 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 。
解题思路:
/** * 动态规划 * 分析: 数组中存放的是金额,小偷可以选择是偷还是不偷 * 定义一个二维数组 dp[length][2] * 其中 dp[i][0]表示第 i+1 家中偷了的最大金额 * dp[i][0] 表示第 i+1 家没偷的最大总金额 * 1.假设第 i 家没有偷,那么第 i+1 家,可以是偷的,也可以是没偷的。 * dp[i][0]=max(dp[i-1][0],dp[i-1][1]) 表示的是第 i+1 家没偷,那么第 i 家没有偷都是可以的,所以我们取两者的最大值即可。 * 2.假设第 i+1 家偷了,那么第 i 家 必须是没有偷的 * dp[i][1]=dp[i-1][0]+nums[i] ,这里nums[i]表示的是第i+1家偷的金额 * 递推公式找出来之后我们再来看下边界条件,第一家可以选择偷,也可以选择不偷 * dp[0][0]=0,第一家没偷 * dp[0][1]=nums[0],第一家偷了 * */ public int Rob01(int[] nums) { // 边界条件处理 if (null == nums || nums.length == 0){ return 0; } int length = nums.length; int[][] dp = new int[length][2]; // 第一家 没偷 dp[0][0] = 0; // 第一节偷了 dp[0][1] = nums[0]; for (int i = 1; i < length; i++) { dp[i][0] = Math.max(dp[i-1][0], dp[i-1][1]); dp[i][1] = dp[i-1][0] + nums[i]; } return Math.max(dp[length-1][0],dp[length-1][1]); } /** * 动态规划优化 * */ public int Rob02(int[] nums) { // 边界条件处理 if (null == nums || nums.length == 0){ return 0; } int length = nums.length; // 第一家 没偷 int dp0 = 0; // 第一节偷了 int dp1 = nums[0]; for (int i = 1; i < length; i++) { int temp = Math.max(dp0, dp1); dp1 = dp0 + nums[i]; dp0 = temp; } return Math.max(dp0, dp1); }