解法一:(动态规划)倒叙 -> 难
import java.util.*;
class Solution79 {
public int rob(int[] nums) {
int n = nums.length;
if (n == 0) return 0;
if (n == 1) return nums[0];
if (n == 2) return Math.max(nums[0],nums[1]);
int max = 0;
int[] max_money = new int[n];
max_money[n-1] = nums[n-1];
max_money[n-2] = nums[n-2];
for (int i = n-3; i >= 0; i--) {
max_money[i] = Math.max(max_money[i+2]+nums[i], max_money[i+1]);
if (i+3<n){
max_money[i] = Math.max(max_money[i+3]+nums[i], max_money[i]);
}
max = Math.max(max, max_money[i]);
}
return max;
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int[] nums = new int[n];
for (int i = 0; i < n; i++) {
nums[i] = in.nextInt();
}
Solution79 sol = new Solution79();
System.out.println(sol.rob(nums));
}
}
解法二:(动态规划)正序 ①定义:dp[i]表示偷到下标为i的家能偷到的最高金额,dp[n] ②初始状态:dp[0]=nums[0],dp[1]=max(nums[0],nums[1]) ③状态转移方程:dp[i] = max(dp[i-1],dp[i-2]+nums[i]),其中dp[i-1]表示不偷下标为i的家;dp[i-2]+nums[i]表示偷下标为i的家
class Solution {
public int rob(int[] nums) {
if (nums == null || nums.length == 0) {
return 0;
}
int length = nums.length;
if (length == 1) {
return nums[0];
}
int[] dp = new int[length];
dp[0] = nums[0];
dp[1] = Math.max(nums[0], nums[1]);
for (int i = 2; i < length; i++) {
dp[i] = Math.max(dp[i - 2] + nums[i], dp[i - 1]);
}
return dp[length - 1];
}
}
注意:
dp[i]
表示到i(第i+1
)家时,能够偷窃到的最高金额- 到
i
(第i+1
家)时,可偷(dp[i - 2] + nums[i]
或者不偷dp[i - 1]
dp
初始化未dp[n]
,初始状态为dp[0] = nums[0]; dp[1] = Math.max(nums[0], nums[1]);
,返回值为dp[length - 1]