leecode198 打家劫舍问题 输出路径


/*
* Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. */ import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * @description: 打家劫舍问题 * @fileName: PACKAGE_NAME.Leecode198 * @author: WWX1062477 * @date: 2022-05-24 10:38 **/ public class Leecode198 { public static List<Integer> rob(int[] nums) { // dp数组定义:dp[i][0]代表不偷第i号房屋所能获得最大金额 // dp[i][1]代表偷第i号房屋所能获得最大金额 int length = nums.length; if (length == 0) { return null; } if (length == 1) { return new ArrayList<Integer>(nums.length); } //定义一个n行2列的数组来表示偷前n号房能活得的最大金额 int[][] dp = new int[length][2]; dp[0][0] = 0;//表示不偷第一间房 dp[0][1] = nums[0];//表示偷第一间房 dp[1][0] = nums[0];//不偷第二号房,那就肯定要偷第一间房 dp[1][1] = nums[1];//偷第二号房,那就肯定不要偷第一间房 for (int i = 2; i < length; i++) { //不偷第i间房,那就肯定偷了第i-1间房 dp[i][0] = dp[i - 1][1]; //偷了第i间房 dp[i][1] = Math.max(dp[i - 2][1] + nums[i], dp[i - 2][1] + nums[i]); } int target = Math.max(dp[length - 1][0], dp[length - 1][1]); List<Integer> track = new ArrayList<>(); for (int i = length - 1; i >= 0; i--) { if (dp[i][1] == target) { target = target - nums[i]; track.add(nums[i]); } } Collections.reverse(track); return track; } public static void main(String[] args) { int[] money1 = {1, 2, 3, 1}; int[] money2 = {2, 7, 9, 3, 1}; // System.out.println("rob(money1) = " + rob(money1)); System.out.println("rob(money2) = " + rob(money2)); } }

198.打家劫舍
dp数组定义:dp[i]代表偷窃0~i号房屋所能获得的最大金额
递推公式:偷窃0~i号房屋所能获得的最大金额也就是要么偷窃i号房屋,那么他只能偷窃i号房屋前面的前面的房屋,也就是dp[i-2]+nums[i],
要么不偷窃i号房屋,那么他可以偷窃i前面的房屋,也就是dp[i-1]
因此递推公式为dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i]);
初始化:需要考虑偷窃第一号房屋和第二号房屋的最大金额
只能偷窃第一号房屋,最大金额肯定为nums[0]
只能偷窃第一号房屋和第二号房屋,若想获得最大金额,只能从一号房屋和二号房屋中选金额最大的


class Solution {
public int rob(int[] nums) {
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];
}
}
输出路径
dp数组定义:dp[i][0]代表不偷第i号房屋所能获得最大金额
dp[i][1]代表偷第i号房屋所能获得最大金额
递推公式:不偷第i号房屋所能获得最大金额就是一定得偷第i号房屋也就是dp[i][0] = dp[i - 1][1]
偷第i号房屋所能获得最大金额有两种情况:

偷i-2号房屋,这个好理解
不偷i-2号房屋,比如说[2,1,1,2]
两者取最大的,也就是dp[i][1] = Math.max(dp[i - 2][1] + nums[i], dp[i - 2][0] + nums[i])
计算路径:得出dp数组后,因为是要计算偷了那几家,因此路径一定是偷了的那家,也就是dp[i][1],然后倒序遍历,如果偷了第i家的最大金额等于target,那就记录路径


class Solution {
public List<Integer> rob(int[] nums) {
if (nums.length == 1) {
return nums[0];
}
int[][] dp = new int[nums.length][2];
dp[0][0] = 0;
dp[0][1] = nums[0];
dp[1][0] = nums[0];
dp[1][1] = nums[1];
for (int i = 2; i < nums.length; i++) {
dp[i][0] = dp[i - 1][1];
dp[i][1] = Math.max(dp[i - 2][1] + nums[i], dp[i - 2][0] + nums[i]);
}
int target = Math.max(dp[nums.length - 1][0],dp[nums.length - 1][1]);
List<Integer> track = new ArrayList<>();
for (int i = nums.length - 1; i >= 0; i--) {
if (dp[i][1] == target) {
target = target - nums[i];
track.add(nums[i]);
}
}
Collections.reverse(track);
return track;
}
}
下一篇:打家劫舍

作者:chenjialong
链接:https://leetcode.cn/problems/house-robber/solution/da-jia-jie-she-dpsi-lu-by-chenjialong-vv9k/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

posted @ 2022-05-24 16:00  WPMA  阅读(157)  评论(0)    收藏  举报