LeetCode:
1.思路
边界思维,只有一个元素和两个元素的初始化考虑
当元素数大于3个时,
逆向思维,是否偷最后一个元素,倒序得出递推公式dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i]);
前者不偷,后者偷,两者取较大值。
2.代码实现
1// 递推公式逆向思考可以得出
2class Solution {
3 public int rob(int[] nums) {
4 int len = nums.length;
5 if (len == 0) {
6 return 0;
7 } else if (len == 1) {
8 return nums[0];
9 }
10
11 int[] dp = new int[len];
12 dp[0] = nums[0];
13 dp[1] = Math.max(dp[0], nums[1]);
14
15 for (int i = 2; i < len; i++) {
16 dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i]);
17 }
18 return dp[len - 1];
19 }
20}
21// 滚动数组,有些小坑得踩一下
22class Solution {
23 public int rob(int[] nums) {
24 int len = nums.length;
25
26 if (len == 0) {
27 return 0;
28 } else if (len == 1) {
29 return nums[0];
30 } else if (len == 2) {
31 return Math.max(nums[0], nums[1]);
32 }
33
34 int[] result = new int[3];
35 result[0] = nums[0];
36 result[1] = Math.max(nums[0], nums[1]);
37
38 for (int i = 2; i < len; i++) {
39 result[2] = Math.max(result[0] + nums[i], result[1]);
40
41 result[0] = result[1];
42 result[1] = result[2];
43 }
44 return result[2];
45 }
46}
3.复杂度分析
时间复杂度:O(n).
空间复杂度:O(1).
LeetCode:
1.思路
考虑首元素和不考虑首元素,即可将环形进行拆解为两个线性数组,取两者之间的较大值即可
2.代码实现
1class Solution {
2 public int rob(int[] nums) {
3 if (nums == null || nums.length == 0) {
4 return 0;
5 }
6
7 int len = nums.length;
8 if (len == 1) {
9 return nums[0];
10 }
11 return Math.max(robAction(nums, 0, len - 1), robAction(nums, 1, len));
12 }
13
14 int robAction(int[] nums, int start, int end) {
15 int x = 0, y = 0, z = 0;
16 for (int i = start; i < end; i++) {
17 y = z;
18 z = Math.max(y, x + nums[i]); //
19 x = y;
20 }
21 return z;
22 }
23}
3.复杂度分析
时间复杂度:O(n).
空间复杂度:O(1).
LeetCode:
1.思路
分两种情况,选择根节点和不选根节点,分别计算两种情况的较大值,并选择两者之间的较大值存入map集合中,返回结果。
2.代码实现
1/**
2 * Definition for a binary tree node.
3 * public class TreeNode {
4 * int val;
5 * TreeNode left;
6 * TreeNode right;
7 * TreeNode() {}
8 * TreeNode(int val) { this.val = val; }
9 * TreeNode(int val, TreeNode left, TreeNode right) {
10 * this.val = val;
11 * this.left = left;
12 * this.right = right;
13 * }
14 * }
15 */
16class Solution {
17 public int rob(TreeNode root) {
18 // 创建一个 Map 来保存已经计算过的节点的最大金额
19 Map<TreeNode, Integer> map = new HashMap<>();
20 // 调用递归方法计算能够偷取的最大金额
21 return robAction(root, map);
22 }
23 // 构建递归方法,计算以 root 为根节点的子树能够偷取的最大金额
24 int robAction(TreeNode root, Map<TreeNode, Integer> map) {
25 // 如果 root 为空,返回 0
26 if (root == null) {
27 return 0;
28 }
29 // 如果map中已经存在以 root 为根节点的子树的最大金额,直接返回该值
30 if (map.containsKey(root)) {
31 return map.get(root);
32 }
33 // money 来保存以 root 为根节点的子树能够偷取的最大金额
34 int money = root.val;
35 // 左:判断 root 的左子节点是否存在,存在则计算左子节点的左子节点和右子节点的最大金额并加到 money 中
36 if (root.left != null) {
37 money += robAction(root.left.left, map) + robAction(root.left.right, map);
38 }
39 // 右:同理
40 if (root.right != null) {
41 money += robAction(root.right.left, map) + robAction(root.right.right, map);
42 }
43 // 结果从选择根节点和不选择根节点之中选取最大值
44 int res = Math.max(money, robAction(root.left, map) + robAction(root.right, map));
45 // 将结果res 存入map中,以便下次使用
46 map.put(root, res);
47 return res;
48 }
49}
3.复杂度分析
时间复杂度:O(n).
空间复杂度:O(logn).