LeetCode198 打家劫舍
题目
你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。
示例 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 。
提示:
1 <= nums.length <= 100
0 <= nums[i] <= 400
方法
动态规划
用dp数组保存每个节点上的最大金额,在当前节点上要么选要么不选,因此第n个节点的最大金额为:dp[n] = max(dp[n-2]+nums[n],dp[n-1]),即选和不选的情况的最大值
- 时间复杂度:O(n)
- 空间复杂度:O(n)
class Solution {
public int rob(int[] nums) {
int n = nums.length;
if(n<1){
return 0;
}else if(n==1){
return nums[0];
}
int[] dp = new int[n];
dp[0] = nums[0];
dp[1] = Math.max(nums[0],nums[1]);
for(int i=2;i<n;i++){
dp[i] = Math.max(dp[i-2]+nums[i],dp[i-1]);
}
return dp[n-1];
}
}
动态规划-进阶版
有第一种代码可知,我们只需两个记录当前节点的前两个节点即可,因此无需采用数组存储,直接定义2个变量记录当前节点的前两个节点,降低空间复杂度
- 时间复杂度:O(n)
- 空间复杂度:O(1)
class Solution {
public int rob(int[] nums) {
int n = nums.length;
if(n<1){
return 0;
}else if(n==1){
return nums[0];
}
int dp0 = nums[0];
int dp1 = Math.max(nums[0],nums[1]);
int dp2 = dp1;
for(int i=2;i<n;i++){
dp2 = Math.max(dp0+nums[i],dp1);
dp0 = dp1;
dp1 = dp2;
}
return dp2;
}
}
输出路径
- 先找到dp数组中最大值出现的第一个位置,说明此位置是被选的
- 然后减去当前nums的数,如果为0说明没有选别的,如果大于0则继续往前找差值所在的第一个位置
import java.util.Arrays;
public class dp {
public int[] rob(int[] nums){
int n = nums.length;
int[] index = new int[n];
int[] dp = new int[n];
if(n == 1) {
dp[0] = nums[0];
return dp;
}
else if(n == 2) {
dp[0] = Math.max(nums[0], nums[1]);
return dp;
}
else{
dp[0] = nums[0];
dp[1] = Math.max(nums[0], nums[1]);
for(int i = 2; i < n; i++){
dp[i] = Math.max(dp[i-2] + nums[i], dp[i-1]);
}
return dp;
}
}
public int[] getIndexArray(int[] nums){
int[] dp = new int[nums.length];
int[] index = new int[nums.length];
int i = 0;
dp = rob(nums);
int ind = Arrays.binarySearch(dp, dp[nums.length - 1]);
index[i] = ind + 1;
while(dp[ind] > nums[ind]){
ind = Arrays.binarySearch(dp, dp[ind] - nums[ind]);
index[++i] = ind + 1;
}
return index;
}
public static void main(String[] args) {
int[] nums = {1, 4, 1, 2, 5, 6, 3, 4, 10};
int[] index = new int[nums.length];
dp dp = new dp();
index = dp.getIndexArray(nums);
for(int i = nums.length - 1; i >= 0; i--){
System.out.println(index[i]);
}
}
}
分类:
LeetCode Hot100
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理