您的位置:首页 > 教育 > 培训 > seo专员工作容易学吗_济南今日疫情通报_关键词排名优化系统_湖南企业seo优化报价

seo专员工作容易学吗_济南今日疫情通报_关键词排名优化系统_湖南企业seo优化报价

2025/2/25 4:33:58 来源:https://blog.csdn.net/qq_45890831/article/details/142912831  浏览:    关键词:seo专员工作容易学吗_济南今日疫情通报_关键词排名优化系统_湖南企业seo优化报价
seo专员工作容易学吗_济南今日疫情通报_关键词排名优化系统_湖南企业seo优化报价

198. 打家劫舍

class Solution {public int rob(int[] nums) {if (nums == null || 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 -2] + nums[i], dp[i - 1]);}return dp[nums.length - 1];}
}

dp[i]:考虑下标i(包括i)以内的房屋,最多可以偷窃的金额为dp[i]

决定dp[i]的因素就是第i房间偷还是不偷。

如果偷第i房间,那么dp[i] = dp[i - 2] + nums[i] ,即:第i-1房一定是不考虑的,找出 下标i-2(包括i-2)以内的房屋,最多可以偷窃的金额为dp[i-2] 加上第i房间偷到的钱。

如果不偷第i房间,那么dp[i] = dp[i - 1],即考 虑i-1房。

然后dp[i]取最大值,即dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);

213. 打家劫舍 II

class Solution {public int rob(int[] nums) {if (nums == null || nums.length == 0)return 0;int len = nums.length;if (len == 1)return nums[0];return Math.max(robAction(nums, 0, len - 1), robAction(nums, 1, len));}int robAction(int[] nums, int start, int end) {int[] dp = new int[end]; // 创建 dp 数组,大小为 endfor (int i = start; i < end; i++) {if (i == start) {dp[i] = nums[i]; // 第一个房屋} else if (i == start + 1) {dp[i] = Math.max(nums[start], nums[i]); // 前两个房屋的最大值} else {dp[i] = Math.max(dp[i - 2] + nums[i], dp[i - 1]); // 状态转移}}return dp[end - 1]; // 返回最后一个房屋的最大抢劫金额}
}

此题是 198. 打家劫舍 的拓展版: 唯一的区别是此题中的房间是 环状排列 的(即首尾相接),而 198. 题中的房间是 单排排列 的;而这也是此题的难点。

环状排列 意味着第一个房子和最后一个房子中 只能选择一个偷窃,因此可以把此 环状排列房间 问题约化为两个 单排排列房间 子问题:

在不偷窃第一个房子的情况下(即 nums[1:]),最大金额是 p 

在不偷窃最后一个房子的情况下(即 nums[:n−1]),最大金额是 p 

综合偷窃最大金额: 为以上两种情况的较大值,即 max(p1,p2) 。

337. 打家劫舍 III

class Solution {public int rob(TreeNode root) {int[] result = robInternal(root);return Math.max(result[0],result[1]);}public int[] robInternal(TreeNode root) {if (root == null) return new int[2];int[] result = new int[2];int[] left = robInternal(root.left);int[] right = robInternal(root.right);result[0] = Math.max(left[0], left[1]) + Math.max(right[0], right[1]);result[1] = left[0] + right[0] + root.val;return result;}
}
方案一

4 个孙子偷的钱 + 爷爷的钱 VS 两个儿子偷的钱 哪个组合钱多,就当做当前节点能偷的最大钱数。这就是动态规划里面的最优子结构

public int rob(TreeNode root) {if (root == null) return 0;int money = root.val;if (root.left != null) {money += (rob(root.left.left) + rob(root.left.right));}if (root.right != null) {money += (rob(root.right.left) + rob(root.right.right));}return Math.max(money, rob(root.left) + rob(root.right));
}作者:房建斌学算法
方案二

我们这次使用哈希表来存储结果,TreeNode 当做 key,能偷的钱当做 value

public int rob(TreeNode root) {HashMap<TreeNode, Integer> memo = new HashMap<>();return robInternal(root, memo);
}public int robInternal(TreeNode root, HashMap<TreeNode, Integer> memo) {if (root == null) return 0;if (memo.containsKey(root)) return memo.get(root);int money = root.val;if (root.left != null) {money += (robInternal(root.left.left, memo) + robInternal(root.left.right, memo));}if (root.right != null) {money += (robInternal(root.right.left, memo) + robInternal(root.right.right, memo));}int result = Math.max(money, robInternal(root.left, memo) + robInternal(root.right, memo));memo.put(root, result);return result;
}作者:房建斌学算法
方案三

我们使用一个大小为 2 的数组来表示 int[] res = new int[2] 0 代表不偷,1 代表偷
任何一个节点能偷到的最大钱的状态可以定义为

当前节点选择不偷:当前节点能偷到的最大钱数 = 左孩子能偷到的钱 + 右孩子能偷到的钱
当前节点选择偷:当前节点能偷到的最大钱数 = 左孩子选择自己不偷时能得到的钱 + 右孩子选择不偷时能得到的钱 + 当前节点的钱数

public int rob(TreeNode root) {int[] result = robInternal(root);return Math.max(result[0], result[1]);
}public int[] robInternal(TreeNode root) {if (root == null) return new int[2];int[] result = new int[2];int[] left = robInternal(root.left);int[] right = robInternal(root.right);result[0] = Math.max(left[0], left[1]) + Math.max(right[0], right[1]);result[1] = left[0] + right[0] + root.val;return result;
}作者:房建斌学算法

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com