Skip to content

198. 打家劫舍

  • DP状态:dp[i]表示偷前i+1家的最大数目;
  • DP转移方程:dp[i] = Math.max(dp[i - 2] + nums[i], dp[i - 1]);
java
public int rob(int[] nums) {
    // 空间优化
    int m = 0, n = nums[0];
    for (int i = 1; i < nums.length; i++) {
        // 计算当前偷与不偷的最优解
        int dp = Math.max(m + nums[i], n);
        m = n;
        n = dp;
    }
    return n;
}

213. 打家劫舍 II

java
public int rob(int[] nums) {
    if (nums.length == 1) {
        return nums[0];
    }
    // 首尾相邻,偷首不能偷尾,取最优解
    return Math.max(
            rob(nums, 0, nums.length - 2),
            rob(nums, 1, nums.length - 1)
    );
}

public int rob(int[] nums, int start, int end) {
    int m = 0, n = nums[start];
    for (int i = start + 1; i <= end; i++) {
        int dp = Math.max(m + nums[i], n);
        m = n;
        n = dp;
    }
    return n;
}

337. 打家劫舍 III

DP状态比较难想,表示为当前节点的两个分支,偷与不偷。

java
public int rob(TreeNode root) {
    int[] arr = dfs(root);
    // 0偷 1不偷
    return Math.max(arr[0], arr[1]);
}

private int[] dfs(TreeNode node) {
    if (node == null) {
        return new int[]{0, 0};
    }
    int[] left = dfs(node.left);
    int[] right = dfs(node.right);
    return new int[]{
            // 偷当前节点,那么左右子节点不能偷
            node.val + left[1] + right[1],
            // 不偷的话,取左右子节点最优解之和
            Math.max(left[0], left[1]) + Math.max(right[0], right[1])
    };
}

基于 MIT 许可发布