如果我们总在等待绝对的一切就绪,那我们将永远无法开始
个人主页:XiaoChen_Android
学习专栏:力扣专栏
发布日期:2022/8/29
原文链接--->点我
像此题类似的求最大利益的一般可以转化为重复子问题用动态规划来求解,找出对应关系即可
S1:首先要判断特殊情况,只有一家,即数组长度为1,那么直接返回这个数即可;
S2:建一个dp数组,用来存当前位置的最大利益,那么第一家的最大利益就是nums的值,第二家就得注意了,他不一定是nums的值,而是前一家和自己这一家中大的那个(这一点读者可以好好分析);
S3:从第三家开始,他的利益可由两种情况得到:第一种:由nums[i] + dp[i - 2]得到,即隔一家的利益再加上自己本身,第二种就是前一家的利益,取其中大的即可,即dp[i] = Math.max(dp[i - 2] + nums[i] , dp[i - 1]);
S4:最后返回nums[len - 1],就是最后一家的利益就是最大利益
dp[0] = nums[0];
dp[1] = Math.max(nums[0] , nums[1]);
for(int i = 2 ; i < len; i++){
dp[i] = Math.max(nums[i] + dp[i - 2] , dp[i - 1]);
}
class Solution {
public int rob(int[] nums) {
int len = nums.length;
if(len == 1) return nums[0];
int[] dp = new int[len];
dp[0] = nums[0];
dp[1] = Math.max(nums[0] , nums[1]);
for(int i = 2 ; i < len; i++){
dp[i] = Math.max(nums[i] + dp[i - 2] , dp[i - 1]);
}
return dp[len - 1];
}
}
思路和上面的思路一样,只是在空间复杂度上进行了优化,这是动态规划的进阶
在解题过程中发现,我们在计算dp[i]的时候,只用到了dp[i - 1]和dp[i - 2],并没有全部用到dp数组,所以我们可以用两个变量来代替就不需要dp数组了,空间复杂度就降低到了O(1)
补充:循环的时候,每次循环是计算偷到当前房子是最大收益;
1.在循环开始时,left表示的是dp[i - 2],max表示的是dp[i - 1];
2.每次算完一个之后,要记得改变left的值和max的值,要分别指到对应的位置,left应等于上一次循环的dp[i - 1](本来是等于dp[i - 2],但是i++了,所以变成了dp[i - 1]),即max;而max应等于上一轮位置计算的最大利益,即t(原因同上);
3.循环结束后,max就为dp[len - 1],而left就为dp[len - 2];
int max = 0;
int left = 0;
for(int i = 0 ; i < len ; i++){
int t = Math.max(max , nums[i] + left);
left = max;
max = t;
}
class Solution {
public int rob(int[] nums) {
int len = nums.length;
if(len == 1) return nums[0];
int max = 0;
int left = 0;
for(int i = 0 ; i < len ; i++){
int t = Math.max(max , nums[i] + left);
left = max;
max = t;
}
return max;
}
}
类似题目推荐:
1.数据结构基础
2.算法专项练习
3.剑指offer专项练习
4.推荐一个学习网站:LeetCode,算法的提升在于日积月累,只有每天练习才能保持良好的状态
如果文章对各位大佬有帮助就支持一下噢,新手尝试,不好的地方请各位大佬多多指教!