HouseRobber 打家劫舍
这道题我在一年前写过,但是时间太长忘了。。。当时还刚学动态规划呢;经过两个小时左右的回忆、优化,我又想起来了,并且在原有基础上又扩展了一步。
首先从HouseRobber1开始,最原始的代码解决方案那肯定是:
private int dfs(int index, int[] nums) {if(index >= nums.length) return 0;int res = 0;for(int i = index; i < nums.length; i++) {res = Math.max(res, nums[i]+dfs(i+2, nums));} return res;}public int rob(int[] nums) {return dfs(0, nums);}
其次是优化成记忆化搜索的过程:
private int dfs(int index, int[] nums, int[] dp) {if(index >= nums.length) return 0;if(dp[index] != 0) return dp[index];for(int i = index; i < nums.length; i++) {dp[index] = Math.max(dp[index], nums[i]+dfs(i+2, nums, dp));} return dp[index];}public int rob(int[] nums) {return dfs(0, nums, new int[nums.length]);}
但是这有一个问题:如果你把dp初始化为0的话,那么一旦要是输入的数据也全为0,那么就起不到记忆化搜索的作用了,所以会超时。
所以这种问题一定要初始化成-1,再次运行:
它的效率是很快的,一般用动态规划时间复杂度是O(n^2)嘛,一般没有记忆化搜索快。
但是这道题可以以时间复杂度O(n)解决:
//时间复杂度O(n),空间复杂度O(n)public int rob(int[] nums) {int[] dp = new int[nums.length];//res是最终结果,tmp表示偷了第i家后,再偷i+2号家所能获取的最大值,dp[i]表示偷第i家所能得到的最大值。int res = -1, tmp = -1, n = dp.length;for(int i = n-1; i >= 0; i--) {dp[i] += nums[i];if(i + 2 < n) {if(i+2 == n-1) tmp = dp[n-1];else if(dp[i+2] > tmp) tmp = dp[i+2];dp[i] += tmp;}//System.out.println(dp[i]);if(res < dp[i]) res = dp[i];}return res;
思路正如注释所示,dp[i]表示偷这一家能获取的最大利益,那么偷第i家所得最多即为偷第i家+第i+2家以后的最大值家。这道题还可以直接用nums数组,不用额外的空间。
//时间复杂度O(n),空间复杂度O(1)public int rob(int[] nums) {//res是最终结果,tmp表示偷了第i家后,再偷i+2号家所能获取的最大值,dp[i]表示偷第i家所能得到的最大值。int res = -1, tmp = -1, n = nums.length;for(int i = n-1; i >= 0; i--) {if(i + 2 < n) {if(i+2 == n-1) tmp = nums[n-1];else if(nums[i+2] > tmp) tmp = nums[i+2];nums[i] += tmp;}if(res < nums[i]) res = nums[i];}return res;}
最后,houseRobber2的解题思路和1是一样的,就是0到n-2算一次,1到n-1.
private int[] dp;private int oneFalse(int[] nums) {int tmp = 0, res = 0, n = nums.length;for(int i = n-1; i > 0 ; i--) {dp[i] += nums[i];if(i+2 < n) {if(i+2 == n-1) tmp = dp[n-1];else if(tmp < dp[i+2]) tmp = dp[i+2];dp[i] += tmp;}if(res < dp[i]) res = dp[i];}return res;}private int oneTrue(int[] nums) {for(int i = 0; i < dp.length; i++) {dp[i] = 0;}int tmp = 0, res = 0, n = nums.length;for(int i = n-2; i >= 0 ; i--) {dp[i] += nums[i];if(i+2 < n-1) {if(i+2 == n-2) tmp = dp[i+2];else if(tmp < dp[i+2]) tmp = dp[i+2];dp[i] += tmp;}if(res < dp[i]) res = dp[i];}return res;}public int rob(int[] nums) {dp = new int[nums.length];return Math.max(oneFalse(nums), oneTrue(nums));}
最初这个代码我是这么写的,我写的时候就发现这个写的太次了,完全应该抽出一个方法嘛。
private int find(int[] nums, int start, int end) {int tmp = 0, res = 0;for(int i = end; i >= start ; i--) {if(i+2 <= end) {if(i+2 == end) tmp = nums[i+2];else if(tmp < nums[i+2]) tmp = nums[i+2];nums[i] += tmp;}if(res < nums[i]) res = nums[i];}return res;}public int rob(int[] nums) {int n = nums.length;if(n == 1) return nums[0];//dp = new int[nums.length];//return Math.max(oneFalse(nums), oneTrue(nums));//因为java在方法中传递数组参数,当方法修改数组时,数组会改变,所以我又new了一个数组int[] tmp = new int[n];for(int i = 0; i < n; i++) {tmp[i] = nums[i];}return Math.max(find(nums, 0, n-2), find(tmp, 1, n-1));}
还得是在这个上面写,我能时常看一下,在leetcode上写,写完我就不看了,时间长了就忘。
HouseRobber 打家劫舍相关推荐
- Leetcode每日一题:198.house-robber(打家劫舍)
思路:明显的动态规划,用money[i]存放打劫至第i家时得到的最多的金额,那么money[i]=max(money[i-2]+nums[i] ,money[i-1]) 因为不能打劫邻居 或者说mon ...
- Python3实现打家劫舍问题
Python3实现打家劫舍问题 原题 https://leetcode-cn.com/problems/house-robber/ 你是一个专业的小偷,计划偷窃沿街的房屋.每间房内都藏有一定的现金,影 ...
- LeetCode 198. 打家劫舍(DP)
1. 题目 你是一个专业的小偷,计划偷窃沿街的房屋.每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警. 给 ...
- leetcode - 198. 打家劫舍
198. 打家劫舍 -------------------------------------- 你是一个专业的小偷,计划偷窃沿街的房屋.每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房 ...
- 模拟卷Leetcode【普通】198. 打家劫舍
198. 打家劫舍 你是一个专业的小偷,计划偷窃沿街的房屋.每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报 ...
- 记录:2022-9-30 打家劫舍 二叉搜索树中第K小的元素 公平锁 磁盘调度
学习时间:2022-9-30 学习内容 1.LeetCode 198. 打家劫舍 思路 dp[i] = dp[i-1]之前的最大值 + num[i] 优化思路:把最大值用一个变量来存 代码 class ...
- 数据结构与算法学习⑥(动态规划 题解 背包和打家劫舍问题)
数据结构与算法学习⑥(动态规划 动态规划 1.初识动态规划 1.1.从贪心说起 1.1.1.贪心的特点 1.1.2.贪心的局限性 1.1.3.贪心失效后怎么办 1.1.4.从最优化问题到递归 1.2. ...
- Python 打家劫舍
每日一练 打家劫舍 你是一个专业的小偷,计划偷窃沿街的房屋.每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报 ...
- [JS][dp]题解 | #打家劫舍(一)#
题解 | #打家劫舍(一)# 题目链接 打家劫舍(一) 题目描述 描述 你是一个经验丰富的小偷,准备偷沿街的一排房间,每个房间都存有一定的现金,为了防止被发现,你不能偷相邻的两家,即,如果偷了第一家, ...
最新文章
- 记一次关于MySQL与PHP的蠢事
- 详解 GNU C 标准中的 typeof 关键字
- SQL Server中一些常见的性能问题
- SAP Commerce的Runtime Attributes
- 【数据结构与算法】字符串匹配 BF算法 RK算法
- JavaScript-面向对象 class 继承
- 浅谈计算机程序设计语言,探讨计算机程序设计语言教学
- C ++ 的 背 影
- Java Applet编程总结
- 企业数据分析,搞定这3个重点事半功倍!
- “你好,世界!” Python教程
- 淡泊明志, 宁静致远--如何在自学之路上爬得更高更远?
- 修改显卡型号(自娱自乐)
- caesar java_Java之Caesar与Vigenere实现
- 腾讯云容器团队内部Istio专题分享
- ATM和电路交换和分组交换区别
- 信息技术选购计算机教案,信息技术七年级西交大版 第二节 选择图像教案.docx...
- 1. 【Part2】 Contour Detection and Hierarchical Image Segmentation【轮廓检测图像分割】
- 一步一步构建量化交易系统
- 如何把cad格式转换成jpg格式?快速把cad转jpg的方法