day47
1、leetcode198 打家劫舍
- 
动规五步法 - dp[i]:偷盗房屋序号为i的房屋时,能偷窃到的最高金额
- 递归公式
- 偷第i间房:dp[i] = dp[i-2] + nums[i]
- 不偷第i间房:dp[i] = dp[i-1]
- dp[i] = max(dp[i-2] + nums[i], dp[i-1])
 
- 初始化
- dp[0] = nums[0]
- dp[1] = max(nums[0], nums[1])
 
- 遍历顺序
- 从前向后遍历
 
- 举例
 
- 
代码 class Solution { public int rob(int[] nums) { if(nums.length == 0) return 0; if(nums.length == 1) return nums[0]; int[] dp = new int[nums.length]; dp[0] = nums[0]; dp[1] = Math.max(nums[0], nums[1]); for(int i=2; i<nums.length; i++) { dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i]); } return dp[nums.length - 1]; } }
2、leetcode213 打家劫舍Ⅱ
- 
首尾房间不能同时被抢 - 情况一:首尾房间都不被抢
- 情况二:第一间房间被抢,最后一间不抢
- 情况三:第一间房间不抢,最后一间被抢
- 综上:最终抢劫金额,应为三种情况的最大值
- 情况一肯定是结果最小,只需比较情况二和情况三就行
- 因为这两种情况对于房⼦的选择余地⽐情况⼀⼤,房⼦⾥的钱数都是⾮负数,所以选择余地⼤,最终结果肯定大于情况一
 
 
- 情况一肯定是结果最小,只需比较情况二和情况三就行
 
- 
代码 class Solution { public int rob(int[] nums) { if(nums.length == 1) return nums[0]; int res1 = robRange(nums, 0, nums.length - 2); int res2 = robRange(nums, 1, nums.length - 1); int res = Math.max(res1, res2); return res; } public int robRange(int[] nums, int start, int end) {//[start, end]闭区间 if( start == end) return nums[start]; int[] dp = new int[nums.length]; dp[start] = nums[start]; dp[start + 1] = Math.max(nums[start], nums[start+1]); for(int i=start+2; i<=end; i++) { dp[i] = Math.max(dp[i-1], dp[i-2]+nums[i]); } return dp[end]; } }
3、leetcode337 打家劫舍Ⅲ
- 
递推法 class Solution { Map<TreeNode, Integer> memo = new HashMap<>();//保存计算后的结果 public int rob(TreeNode root) { if(root == null) return 0; if(memo.containsKey(root)) return memo.get(root); //偷父节点,然后去下下家偷 int val1 = root.val; if(root.left != null) { val1 += rob(root.left.left) + rob(root.left.right); // 跳过root->left } if(root.right != null) { val1 += rob(root.right.left) + rob(root.right.right); // 跳过root->right } //不偷父节点,偷其左右孩子节点 int val2 = rob(root.left) + rob(root.right);// 考虑root的左右孩子 int res = Math.max(val1, val2); memo.put(root, res); //memo记录结果 return res; } }
- 
动态规划 class Solution { public int rob(TreeNode root) { int[] res = robTree(root); return Math.max(res[0], res[1]); } public int[] robTree(TreeNode cur) { //下标为0记录不偷该节点所得到的的最大金钱,下标为1记录偷该节点所得到的的最大金钱。 int res[] = new int[2]; if (cur == null){ return res; } int[] left = robTree(cur.left);//左 int[] right = robTree(cur.right);//右 //中 res[0] = Math.max(left[0], left[1]) + Math.max(right[0], right[1]); //不偷cur【左右孩子可以偷,但是具体要不要偷,看值的大小】 res[1] = cur.val + left[0] + right[0];//偷cur【左右孩子不能偷】 return res; } }
 
                    
                
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号