打家劫舍
你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。
示例 1:
输入:[1,2,3,1]
输出:4
解释:偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。
偷窃到的最高金额 = 1 + 3 = 4 。
示例 2:
输入:[2,7,9,3,1]
输出:12
解释:偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。
偷窃到的最高金额 = 2 + 9 + 1 = 12 。
题解
动态规划法
// 数组只有两位数就比较返回最大值。
if(nums == null || nums.length == 0){
System.out.println(0);
return 0;
}
if(nums.length == 1){
System.out.println(nums[0]);
return nums[0];
}
时间复杂度 o(n) 空间复杂度o(n)
声明一个数组记录前 n 间房最大金额
int[] je = new int[nums.length];
je[0] = nums[0];
je[1] = Math.max(nums[0],nums[1]);
/*
je[0] = nums[0] = 2
je[1] = max(je[0],nums[1]) = 7
je[2] = max(je[1],je[0] + nums[2]) = 11
je[3] = max(je[2],je[1] + nums[3]) = 11
je[4] = max(je[3],je[2] + nums[4]) = 12
通项公式 = max(je[n-1],je[n-2] + nums[n])
*/
for (int i = 2; i < nums.length; i++) {
je[i] = Math.max(je[i-1],je[i-2] + nums[i]);
}
System.out.println(je[je.length-1]);
根据上面代码可以改进为下方代码块,节省空间
class Solution {
public int rob(int[] nums) {
// 数组只有两位数就比较返回最大值。
if(nums == null || nums.length == 0){
System.out.println(0);
return 0;
}
if(nums.length == 1){
System.out.println(nums[0]);
return nums[0];
}
// 声明一个数组记录前 n 间房最大金额
// 时间复杂度o(n) 空间复杂度o(1)
int first = nums[0];
int second = Math.max(nums[0],nums[1]);
for (int i = 2; i < nums.length; i++) {
int temp = second;
second = Math.max(first+nums[i],second);
first = temp;
}
System.out.println(Math.max(first,second));
return Math.max(first,second);
}
}